序列化-请求数据校验。。。。。。
Posted ls13691357174
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了序列化-请求数据校验。。。。。。相关的知识,希望对你有一定的参考价值。
序列化
拿到所有的角色数据
1.urls.py
2.models.py 假设只有3个角色
3.views.py
from api import models
import json
json只能序列化python的基本数据类型!!!!
QueryDict是django定义的类!!!!
所以以下这种操作会报错!!!
4.解决方案:取某个字段,然后转成list数据,再转成json数据。
返回数据:注意汉字都变成字节码了!!!
5.显示中文 ensure_ascii=False
- json序列化方法
ret = json.dumps(ser.data, ensure_ascii=False)
运行结果:
方式一:Serializer
1.from rest_framework import serializers
serializers.Serializer
- from rest_framework import serializers
- class RolesSerializers(serializers.Serializer):
- title = serializers.CharField()
2.
3.
4.运行结果
5.title是固定的吗???能不能随便写,比如ttt
运行结果:
注意:必须和数据库的字段一致才行,不能随便写。否则会报错。
普通字段
6.也有id字段,数字类型。
运行结果:
7.对单个对象序列化
代码:
urls.py url(r‘^(?P<version>[v1|v2]+)/roles/$‘, views.RolesView.as_view()), views.py from rest_framework import serializers class RolesSerializers(serializers.Serializer): id = serializers.IntegerField() title = serializers.CharField() class RolesView(APIView): def get(self, request, *args, **kwargs): roles = models.Role.objects.all().first() ser = RolesSerializers(instance=roles, many=False) # ser.data 已经是转换完成的结果 ret = json.dumps(ser.data, ensure_ascii=False) # {"id": 1, "title": "医生"} return HttpResponse(ret)
1.urls.py
2.models.py 表结构
分组表数据
用户表数据,进行分组,都是A组
3.views.py 查看set.data
打印结果:ser.data 是OrdereDict类型。json能解析该类型的数据。
4.
运行结果:
choices 字段
5.如果要显示用户类型怎么办??? usert_py 下拉框
views.py
显示数字
运行结果:用户类型显示的是数字。
6. source=‘指定对应数据库字段‘。 usert_type这个字段也可以用xxx 表示
运行结果:
如何让分组显示中文汉字呢???
7.序列化某个字段,字段写了source. 取得user_type这个值,在源码 会自动判断该字段是否能被调用。能则字段加括号调用,如果不能则页面之间显示结果。
比如user_type字段是数字不能调用,则返回数字。
row.get_user_type_display 该字段可被调用。会自动加括号,帮我们去执行。
view.py
运行结果:显示中文汉字!!!
8.接下来,显示分组。group字段 1对多
views.py
运行结果:gp是一个对象
一对多字段
9.如果想去分组的id怎么办???group.id
也可以group.title 显示title组名
运行结果:
多对多字段
10.接下来,取当前用户喜欢的所有角色 多对多的关系
用户——角色 关系表 添加数据
views.py
运行结果:
自定义函数:用于某些字段用source取不到的情况
11.多对多字段 用source做不到特别细的粒度,所有用另一种方式:自定义函数。
views.py 自定义函数:返回一个[]
运行结果:
12.显示一个列表[ {},{} ] 的类型
运行结果:显示一个列表[ {},{} ]
13.以上数据写死了,我们需要动态获取。
获取所有对象,遍历
运行结果:
方式二:ModelSerializer
1.继承的类 serializers.ModelSerializer
2.看源码: ModelSerializer 继承了 Serializer类
3.字段不用自己写了
4.运行结果:数据全都自动生成了。但是只能完成基本的数据
5.如果想要进一步拿数据,就需要自己定义了
运行结果:
6.choices 类型字段 显示中文
运行结果:
7.多对多字段 自定义函数
运行结果:
8.自定义 一个字段
1.
2.
3.功能是一样的
4.x1字段 自定义返回结果:xxxxx
运行结果:
打印结果:value: username字段对应的值
自动序列化连表 depth = 1
# 1取中文 0取id 0 ~ 10 多对多、一对多都会自动取值。
1.原数据
运行结果:
2.字段想要中文怎么办?????
- depth = 1 # 1取中文 0取id 0 ~ 10 多对多、一对多都会自动取值。
运行结果:
3.depth = 0
4.fields也适用
运行结果:
生成链接
1.
2.id生成url
urls.py 起别名,通过别名反向生成url
views.py 分组视图
3.userinfo视图
- HyperlinkedIdentityField 默认生成url
- group = serializers.HyperlinkedIdentityField(view_name=‘gp‘)
运行结果:
4.分组视图 还需要再加上一个参数。
运行结果: 我们只有一个组,但是后面的数字不对应!!!
5.我们只有一个组,但是后面的数字不对应!!! 数据有问题怎么办呢???
6.(?P<xxx>)分组别名改了 xxx
urls.py
views.py
- group = serializers.HyperlinkedIdentityField(view_name=‘gp‘,lookup_field=‘group_id‘,lookup_url_kwarg=‘pk‘)
运行结果: 数据对应了
8. 分组视图 (?P<xxx>)
9.查看分组详细
代码:
url(r‘^(?P<version>[v1|v2]+)/group(?P<pk>d+)/$‘, views.GroupView.as_view(),name=‘gp‘), from rest_framework import serializers # class UserInfoSerializers(serializers.Serializer): class UserInfoSerializers(serializers.ModelSerializer): # 根据分组id反向生产url group = serializers.HyperlinkedIdentityField(view_name=‘gp‘,lookup_field=‘group_id‘,lookup_url_kwarg=‘pk‘) class Meta: model = models.UserInfo fields = [‘id‘,‘username‘,‘password‘,‘group‘] depth = 1 # 1取中文 0取id 0 ~ 10 class UserinfoView(APIView): def get(self, request, *args, **kwargs): users = models.UserInfo.objects.all() # 1.实例化,一般是将数据封装到对象:__new__,__init__ # 一个对象, Serializer类处理; self.to_representation # QuerySet集合,ListSerializer类处理; self.to_representation set = UserInfoSerializers(instance=users, many=True,context={‘request‘: request}) set.data ret = json.dumps(set.data, ensure_ascii=False) return HttpResponse(ret) # 序列化数据分组 class GroupSerializers(serializers.ModelSerializer): class Meta: model = models.UserGroup fields = "__all__" # 把id换成路由。 class GroupView(APIView): def get(self, request, *args, **kwargs): pk = kwargs.get(‘pk‘) obj = models.UserGroup.objects.filter(pk=pk).first() ser = GroupSerializers(instance=obj,many=False) # 单个对象 ret = json.dumps(ser.data,ensure_ascii=False) # 中文 return HttpResponse(ret)
序列化源码流程:ModelSerializer
0.from rest_framework import serializers
1.创建类,2.实例化类
代码:
from rest_framework import serializers # class UserInfoSerializers(serializers.Serializer): class UserInfoSerializers(serializers.ModelSerializer): # 根据分组id反向生产url group = serializers.HyperlinkedIdentityField(view_name=‘gp‘,lookup_field=‘group_id‘,lookup_url_kwarg=‘pk‘) class Meta: model = models.UserInfo fields = [‘id‘,‘username‘,‘password‘,‘group‘] depth = 1 # 1取中文 0取id 0 ~ 10 class UserinfoView(APIView): def get(self, request, *args, **kwargs): users = models.UserInfo.objects.all() # 1.实例化,一般是将数据封装到对象:__new__,__init__ set = UserInfoSerializers(instance=users, many=True,context={‘request‘: request}) ret = json.dumps(set.data, ensure_ascii=False) return HttpResponse(ret)
3.类在实例化之前会执行什么方法???
python 当一个类实例化的时候先会执行构造方法__init__,其实在构造方法之前会先执行__new__方法.
自定义类下没有new 和init方法,接下去继承类里找。
4.
5.ModelSerializer 也没有没有new 和init方法,接下去继承类里找。
6.Serializer 还是没有没有new 和init方法,接下去继承类里找。
- BaseSerializer 类里面有new 和init方法
7.
8.在new方法做了区分处理。 QuerySet实际处理它的类是 ListSerializer类
9.接下来看 set.data 做了什么事???
点data 继续往下走
10. to_representation
视图加注释
11. 继续往下走,应该抛异常, 但是程序没有抛异常,说明找错了。
12. to_representation 应该先从自定义类开始找。类里面没有该方法,继续往下走
13. ModelSerializer 没有 to_representation
14. Serializer 有 to_representation
15.
16. 方便查看 get_attribute 方法 做了什么事???
17. 看字段里面有没有 get_attribute 方法。 没有去父类找
18. Field 有 get_attribute 方法。
19.
20.
21.加注释
22.
23.
24.
判断是否是函数类型,2种方法。
请求数据校验:
运行结果:传值了
打印结果:
运行结果:没有传值了
打印结果: 接收值为空
1.那么问题来了: 对数据进行校验,假设不允许值为空!!!该怎么办呢???
运行结果:
没有传值后的打印结果
2.自定义提示信息
打印结果:
title有值
打印结果:
只拿值
打印结果
3.自定义验证规则 假设你写的规则必须以666开头
运行结果:
打印结果:
代码:
############################ 验证########################## # 自定义验证规则 class xxxValidator(object): def __init__(self, base): self.base = base def __call__(self, value): # 数据一提交 就会执行__call__方法。 if not value.startswith(self.base): message = ‘标题必须以 %s开头!‘ % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): # 执行验证之前调用,serializer_fields是当前字段对象 pass # 序列化数据 class UsergroupSerializers(serializers.Serializer): # title = serializers.CharField(error_messages={‘required‘:‘标题不能为空!‘}) # 写的标题必须也什么开头。 title = serializers.CharField(error_messages={‘required‘:‘标题不能为空!‘},validators=[xxxValidator(‘老男人‘),]) # 验证用户请求数据 class UsergroupView(APIView): def post(self, request, *args, **kwargs): ser = UsergroupSerializers(data=request.data) if ser.is_valid(): print(ser.validated_data[‘title‘]) else: print(ser.errors) return HttpResponse(‘提交数据‘)
总结:
序列化: 部分总结: 1. 写类 class RolesSerializer(serializers.Serializer): id = serializers.IntegerField() title = serializers.CharField() class UserInfoSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo # fields = "__all__" fields = [‘id‘,‘username‘,‘password‘,] 2. 字段 a. title = serializers.CharField(source="xxx.xxx.xx.xx") b. title = serializers.SerializerMethodField() class UserInfoSerializer(serializers.ModelSerializer): rls = serializers.SerializerMethodField() # 自定义显示 class Meta: model = models.UserInfo fields = [‘id‘,‘username‘,‘password‘,‘rls‘,] # 自定义方法 def get_rls(self, row): role_obj_list = row.roles.all() ret = [] for item in role_obj_list: ret.append({‘id‘:item.id,‘title‘:item.title}) return ret c. 自定义类 fields = [‘id‘,‘username‘,‘password‘,‘group‘] depth = 1 # 1取中文 0取id 0 ~ 10 3. 自动序列化连表 class UserInfoSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo # fields = "__all__" fields = [‘id‘,‘username‘,‘password‘,‘group‘,‘roles‘] depth = 1 # 0 ~ 10 4. 生成链接 class UserInfoSerializer(serializers.ModelSerializer): group = serializers.HyperlinkedIdentityField(view_name=‘gp‘,lookup_field=‘group_id‘,lookup_url_kwarg=‘xxx‘) class Meta: model = models.UserInfo # fields = "__all__" fields = [‘id‘,‘username‘,‘password‘,‘group‘,‘roles‘] depth = 0 # 0 ~ 10 class UserInfoView(APIView): def get(self,request,*args,**kwargs): users = models.UserInfo.objects.all() ser = UserInfoSerializer(instance=users,many=True,context={‘request‘: request}) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret) 源码: 一个对象, Serializer类处理; QuerySet集合,ListSerializer类处理; # ser.data 请求数据校验: class XXValidator(object): def __init__(self, base): self.base = base def __call__(self, value): if not value.startswith(self.base): message = ‘标题必须以 %s 为开头。‘ % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): """ This hook is called by the serializer instance, prior to the validation call being made. """ # 执行验证之前调用,serializer_fields是当前字段对象 pass class UserGroupSerializer(serializers.Serializer): title = serializers.CharField(error_messages={‘required‘:‘标题不能为空‘},validators=[XXValidator(‘老男人‘),]) class UserGroupView(APIView): def post(self,request,*args,**kwargs): ser = UserGroupSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data[‘title‘]) else: print(ser.errors) return HttpResponse(‘提交数据‘)
以上是关于序列化-请求数据校验。。。。。。的主要内容,如果未能解决你的问题,请参考以下文章