• 序列化组件


    序列化组件

    Serializer类(了解)- 偏底层,开发效率不高

    ModelSerializer类(重中之重) - 开发运用阶段才有的序列化方式,开发效率高

    ListSerializer类(正常)- 完成群增,群改接口的辅助序列化类

    为什么要使用序列化:后台的数据多以后台类的对象存在,经过序列化后,就可以格式化成能返回给前台的数据

    序列化

    一、视图类的三步操作
    1)ORM操作数据库拿到资源数据
    2)格式化(序列化)成能返回给前台的数据
    3)返回格式化后的数据

    二、视图类的序列化操作
    1)直接将要序列化的数据传给序列化类
    2)要序列化的数据如果是单个对象,序列化的参数many为False,数据如果是多个对象(list,queryset)序列化的参数many为True

    三、序列化类
    1)model了中要反馈给前台的字段,在序列化类中要进行声明,属性名必须就是model的字段名,且Field类型也要保持一致(不需要明确规则)
    2)model了中不需要反馈给前台的字段,在序列化类中不需要声明(省略)
    3)自定义序列化字段用 SerializerMethodField() 作为字段类型,该字段的值来源于 get_自定义字段名(self, obj) 方法的返回值

    反序列化

    一、视图类的三步操作
    1)从请求对象中拿到前台的数据
    2)校验前台数据是否合法
    3)反序列化成后台Model对象与数据库交互

    二、视图类的反序列化操作
    1)将要反序列化的数据传给序列化类的data参数
    2)要反序列化的数据如果是单个字典,反序列化的参数many为False,数据如果是多个字典的列表,反序列化的参数many为True

    三、反序列化类
    1)系统的字段,可以在Field类型中设置系统校验规则(name=serializers.CharField(min_length=3))
    2)required校验规则绝对该字段是必校验还是可选校验字段(默认required为True,数据库字段有默认值或可以为空的字段required可以赋值为False)
    3)自定义的反序列字段,设置系统校验规则同系统字段,但是需要在自定义校验规则中(局部、全局钩子)将自定义反序列化字段取出(返回剩余的数据与数据库交互)
    4)局部钩子的方法命名 validate_属性名(self, 属性的value),校验规则为 成功返回属性的value 失败抛出校验错误的异常
    5)全局钩子的方法命名 validate(self, 所有属性attrs),校验规则为 成功返回attrs 失败抛出校验错误的异常

    from rest_framework import serializers
    class UserSerializer(serializers.Serializer):
        # model已有的属性字段
        #   如果要参与序列化,名字一定要与model的属性同名
        #   如果不参与序列化的model属性,在序列化类中不做声明
    
        name = serializers.CharField()
        age = serializers.IntegerField()
        height = serializers.DecimalField(max_digits=5, decimal_places=2)
        # sex = serializers.IntegerField()
    
        # 自定义序列化字段,序列化的属性值由方法来提供,
        #   方法的名字:固定为 get_属性名,
        #   方法的参数:序列化对象,序列化的model对象
        #   强烈建议自定义序列化字段名不要与model已有的属性名重名
    
        gender = serializers.SerializerMethodField()
        def get_gender(self, obj):
            # print('>>>>>>', type(self))
            # print('>>>>>>', type(obj))
            return obj.get_sex_display()
    
    
    from . import models
    class UserDeserializer(serializers.Serializer):
        # 系统校验规则
    
        # 系统必须反序列化的字段
        # 序列化属性名不是必须与model属性名对应,但是与之对应会方便序列化将校验通过的数据与数据库进行交互
        name = serializers.CharField(min_length=3, max_length=64, error_messages={
            'required': '姓名必填',
            'min_length': '太短',
        })
        pwd = serializers.CharField(min_length=3, max_length=64)
    
        # 系统可选的反序列化字段:没有提供不进行校验(数据库中有默认值或可以为空),提供了就进行校验
        age = serializers.IntegerField(min_value=0, max_value=150, required=False)
    
        # 自定义反序列化字段:一定参与校验,且要在校验过程中,将其从入库的数据中取出,剩余与model对应的数据才会入库
        re_pwd = serializers.CharField(min_length=3, max_length=64)
    
        # 自定义校验规则:局部钩子,全局钩子
        # 局部钩子:validate_字段名(self, 字段值)
        # 规则:成功返回value,失败抛异常
        def validate_aaa(self, value):
            if 'g' in value.lower():
                raise serializers.ValidationError('名字中不能有g')
            return value
    
        # 全局钩子:validate(self, 所有校验的数据字典)
        # 规则:成功返回attrs,失败抛异常
        def validate(self, attrs):
            # 取出联合校验的字段们:需要入库的值需要拿到值,不需要入库的需要从校验字段中取出
            pwd = attrs.get('pwd')
            re_pwd = attrs.pop('re_pwd')
            if pwd != re_pwd:
                raise serializers.ValidationError({'re_pwd': '两次密码不一致'})
            return attrs
    
        # create重写,完成入库
        def create(self, validated_data):
            return models.User.objects.create(**validated_data)
    
    
    # 重点 ModelSerializer
    from rest_framework.serializers import ModelSerializer
    from . import models
    # 整合序列化与反序列化
    class UserModelSerializer(ModelSerializer):
        # 将序列化类与Model类进行绑定
        # 设置序列化与反序列化所有字段(并划分序列化字段与反序列化字段)
        # 设置反序列化的局部与全局钩子
    
        # 自定义反序列化字段,校验规则只能在声明自定义反序列化字段时设置,且一定是write_only
        re_pwd = serializers.CharField(min_length=3, max_length=64, write_only=True)
    
        class Meta:
            model = models.User
            fields = ['name', 'age', 'height', 'gender', 'pwd', 're_pwd']
            extra_kwargs = {
                'name': {
                    'required': True,
                    'min_length': 3,
                    'error_messages': {
                        'min_length': '太短'
                    }
                },
                'age': {
                    'required': True,  # 数据库有默认值或可以为空字段,required默认为False
                    'min_value': 0
                },
                'pwd': {
                    'required': True,
                    'write_only': True,  # 只参与反序列化
                },
                'gender': {
                    'read_only': True,  # 只参与序列化
                },
            }
    
        def validate_name(self, value):
            if 'g' in value.lower():
                raise serializers.ValidationError('名字中不能有g')
            return value
    
        def validate(self, attrs):
            pwd = attrs.get('pwd')
            re_pwd = attrs.pop('re_pwd')
            if pwd != re_pwd:
                raise serializers.ValidationError({'re_pwd': '两次密码不一致'})
            return attrs
    
        # ModelSerializer已经帮我们重写了入库方法
    
    

    总结

    1)序列化与反序列功能可以整合成一个类,该类继承ModelSerializer
    2)继承ModelSerializer类的资源序列化类,内部包含三部分
    Meta子类、局部钩子、全局钩子
    注:create和update方法ModelSerializer已经重写了,使用不需要重写
    3)在Meta子类中:
    用model来绑定关联的Model类
    用fields来设置所有的序列化反序列化字段
    用extra_kwargs来设置系统的校验规则
    4)重要的字段校验规则:
    read_only校验规则,代表该字段只参与序列化
    write_only校验规则,代表该字段只参与反序列化
    required校验规则,代表该字段在反序列化是是否是必填(True)还是选填(False),不能和read_only一起使用(规则冲突)
    规则细节:
    如果一个字段有默认值或是可以为空,没设置required规则,默认为False,反之默认值为True
    如果一个Model字段即没有设置read_only也没设置write_only,该字段默认参与序列化及反序列化
    5)自定义序列化字段:在Model类中,定义方法属性(可以返回特殊值,还可以完成连表操作),在序列化类的fields属性中可以选择性插拔
    6)自定义反序列化字段:在Serializer类中,自定义校验字段,校验规则也只能在声明字段时设置,自定义的反序列化字段(如re_pwd),
    必须设置write_only为True

    """
    1、新建django项目、注册drf、设置国际化、配置数据库(修改数据库操作模块)、自定义Model类(设置文件类型字段和选项字段)、配置media及开放media资源接口
    2、继承Serializer类的基础序列化类,可以将对象序列化成前台所需数据
    3、继承Serializer类的基础反序列化类,可以指定一系列前台提供的数据的校验规则,确保数据安全
    	class BookSerializer(serializers.Serializer):
    		name = serializers.CharField(min_length=3, max_length=10)
    		
    		# 自定义序列化字段
    		my_name = serializers.SerializerMethodField()
    		def get_my_name(self, obj):
    			return 'my_name的值,一般与obj有关系'
    			
    		# 自定义反序列化字段
    		re_name = serializers.CharField(min_length=3, max_length=10)
    		
    		# required | write_only | read_only
    		# 局部钩子
    		def validate_name(self, value):
    			if 'g' in name:
    				raise serializers.ValidationError('名字异常')
    			return value
    		# 全局钩子
    		def validate_name(self, attrs):
    			attrs.pop('re_name')
    			# 失败抛异常,成功返回attrs
    		# 需求有增和改还需要重写create和update
    		
    		
    		
    	
    4、重点掌握整合序列化与反序列为一体的继承ModelSerializer类的序列化类
    	设置序列化与反序列化字段,并进行区分
    	提供自定义序列化字段以及自定义反序列化字段
    	设置系统校验规则、局部钩子校验规则与全局钩子校验规则
    	class Book(models.Model):
    		# 自定义序列化字段
    		@property
    		def my_name(self):
    			return 'my_name的值,与Book类对象self有关'
    		
    	class BookModelSerializer(ModelSerializer):
    		# 自定义反序列化字段,系统校验规则必须在声明中属性,在全局钩子移除
    		re_name = serializers.CharField(min_length=3, max_length=10, write_only=True)
    		class Meta:
    			model = Book
    			fields = ('name', 'price', 'my_name', 're_name')
    			extra_kwargs = {
    				# 系统校验
    				'name': {
    					'required': True
    				}
    			}
    		# 局部全局钩子,和Serializer方式一样,且不用重写create和update方法
    """
    
  • 相关阅读:
    系统调用与库函数
    在树莓派上 搭建sqlite数据库
    (转)inux Read系统调用
    查看当前日期是这一年的第几天
    求解某个范围内的全部完数
    求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。
    输入三个整数x,y,z,请把这三个数据由大到小输出。
    模仿ArrayList底层实现
    可视化日历
    Oracle之约束条件1:主键约束
  • 原文地址:https://www.cnblogs.com/aden668/p/11907498.html
Copyright © 2020-2023  润新知