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

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

技术分享图片

  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

 


以上是关于序列化-请求数据校验。。。。。。的主要内容,如果未能解决你的问题,请参考以下文章

rest_framwork组件

Android App 安全的HTTPS 通信

Struts2请求参数合法性校验机制

Django REST framework 简介

Django REST framework框架详解

68 drf 响应类reponse 序列化数据校验与写入