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


    序列化

    拿到所有的角色数据

    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
  • 相关阅读:
    CSS初识
    HTML 初识
    索引
    表查询前之数据导入
    mysql练习2
    AMP+EPP3.0的开发环境配置
    C++异步编程资料汇集贴
    Windows8中如何打包和安装一个本地的Metro类型应用(转)
    std::string, std::wstring, wchar_t*, Platform::String^ 之间的相互转换
    windows RT开发笔记:WinRT DLL及其调用研究
  • 原文地址:https://www.cnblogs.com/ls13691357174/p/9879744.html
Copyright © 2020-2023  润新知