序列化-请求数据校验。。。。。。

序列化

拿到所有的角色数据

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

  1. json序列化方法

 ret = json.dumps(ser.data, ensure_ascii=False)

运行结果:

 

方式一:Serializer

1.from rest_framework import serializers

 serializers.Serializer

  1. from rest_framework import serializers
  2. class RolesSerializers(serializers.Serializer):
  3. 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)
View Code

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.字段想要中文怎么办????? 

  1. depth = 1 # 1取中文 0取id 0 ~ 10 多对多、一对多都会自动取值。

运行结果:

3.depth = 0

4.fields也适用

运行结果:

 

生成链接

1.

2.id生成url

urls.py    起别名,通过别名反向生成url

views.py   分组视图

 

3.userinfo视图     

  1. HyperlinkedIdentityField 默认生成url
  1. group = serializers.HyperlinkedIdentityField(view_name='gp')

 

运行结果:

4.分组视图 还需要再加上一个参数。

运行结果:   我们只有一个组,但是后面的数字不对应!!!

 5.我们只有一个组,但是后面的数字不对应!!!  数据有问题怎么办呢???

 

6.(?P<xxx>)分组别名改了 xxx

urls.py

 

 views.py

  1. 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)
View Code

序列化源码流程: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)
View Code

3.类在实例化之前会执行什么方法???

 python 当一个类实例化的时候先会执行构造方法__init__,其实在构造方法之前会先执行__new__方法.

自定义类下没有new 和init方法,接下去继承类里找。

 

4. 

5.ModelSerializer 也没有没有new 和init方法,接下去继承类里找。


6.Serializer 还是没有没有new 和init方法,接下去继承类里找。

  1. 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('提交数据')
View Code

总结:

 序列化:
            部分总结:
                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('提交数据')
View Code
原文地址:https://www.cnblogs.com/ls13691357174/p/9879744.html