Serializer和ModelSerializer

1.序列化和反序列化

序列化,是指将复杂的QuerySet和Model类型转换成Python基本数据类型,从而将这些基本数据类型以JSON的形式响应给客户端。

反序列化则和序列化相反,是指将Http请求中传入的JSON数据转换成复杂的数据类型,从而保存在数据库中。

在REST Framework中,提供了多个用于序列化操作的类,但常用的也就如下两个:

  • Serializer:进行序列化基本的类;
  • ModelSerializer:继承于Serializer,内部实现了通用的序列化逻辑,其中包含了与Model字段对应的字段,可以快速对Model进行序列化。

使用时需要导入对应模块:

from  rest_framework import  serializers

接下来我们就分别看看这两个序列化操作的类。

2.0 Serializer

Serializer进行序列化的基本格式如下:

class UserInfoSerializer(serializers.Serializer):
    id = serializers.CharField(read_only=True)
    username = serializers.CharField(min_length=3, max_length=20, error_messages={'required': '该字段必填'})
    img = serializers.ImageField(required=False)
    nick_name = serializers.CharField(max_length=20)
    address = serializers.CharField(max_length=255)
    xxx = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = User

    # 自定义显示 多对多 字段
    def get_xxx(self, row):
        '''row: 传过来的正是 User表的对象'''

        users = row.username  # 获取用户名
        return users

    # 定义创建语法:ser.save()执行,就会立刻调用create方法用来创建数据
    def create(self, validated_data):
        '''validated_data: 表单或者vue请求携带的json:
        {"username":"zhangsan","password":"123456"}'''

        # https://www.cnblogs.com/xiaonq/p/7978409.html
        return User.objects.create(**validated_data)

    # 定义更新方法
    def update(self, instance, validated_data):

        '''
        instance : 查询的对象
        validated_data : postman提交的json数据
        {"username":"zhangsan","password":"123456"}
        '''
        if validated_data.get('username'):
            instance.username = validated_data['username']
            instance.save()
        return instance

    # 定义单一字段验证的方法
    def validate_name(self, value):
        if value == 'root':
            raise serializers.ValidationError('不能创建root管理员账号')

        return value

    # 定义多字段验证方法
    def validate(self, attrs):
        print(attrs)

        if attrs.get("username") == 'admin':
            raise serializers.ValidationError('不能创建admin用户')
        return attrs

这个序列化类中有两部分:

  • 1.定义了要进行序列化的字段;这些字段负责将Python类型转换成JSON类型,即序列化的过程;
  • 2.定义了当serializer.save()时用于生成Model对象的create()和update()方法,这两方法负责将JSON类型的数据转换成Python类型的数据,即反序列化的过程。

整个序列化类的实现就这么简单

关于DRF的View相关部分会在之后的文章中详细总结。

2.1Serializer的方法和属性

1.save()

在调用serializer.save()时,会创建或者更新一个Model实例(调用create()或update()创建),具体根据序列化类的实现而定,如:

# .save() will create a new instance.``serializer ``=` `StudentSerializer(data``=``data)` `# .save() will update the existing `comment` instance.``serializer ``=` `StudentSerializer(comment, data``=``data)

2.create()、update()

Serializer中的create()和update()方法用于创建生成一个Model实例,在使用Serializer时,如果要保存反序列化后的实例到数据库,则必须要实现这两方法之一,生成的实例则作为save()返回值返回。方法属性validated_data表示校验的传入数据。

3. is_valid()

当反序列化时,在调用Serializer.save()之前必须要使用is_valid()方法进行校验,如果校验成功返回True,失败则返回False,同时会将错误信息保存到serializer.errors属性中。

4.data

serializer.data中保存了序列化后的数据。

5.errors

当serializer.is_valid()进行校验后,如果校验失败,则将错误信息保存到serializer.errors属性中。

6.Serializer中的Field

在定义Model时,我们通过models.获取了各种不同的字段,作为数据库中表的一个列。而在Serializer中,也需要通过`serializers.的形式获取对应Model的字段,用来在JSON数据和Python数据类型之间进行转换,此外还可以根据Field中传入的属性进行校验、设置默认值。以下对常用Serializer的Field进行整理。

使用时,需要导入所在模块:

from  rest_framework  import  serializers

1.CharField

对应models.CharField,同时如果指定长度,还会负责校验文本长度。

max_length:最大长度;
min_length:最小长度;
allow_blank=True:表示允许将空串做为有效值,默认False;

2.EmailField

对应models.EmailField,验证是否是有效email地址。

3.IntegerField

对应models.IntegerField,代表整数类型

4.FloatField

对应models.FloatField,代表浮点数类型

5.DateTimeField

对应models.DateTimeField,代表时间和日期类型。

format=‘YYYY-MM-DD hh:mm’:指定datetime输出格式,默认为DATETIME_FORMAT值。
需要注意,如果在 ModelSerializer 和HyperlinkedModelSerializer中如果models.DateTimeField带有auto_now=True或者auto_add_now=True,则对应的serializers.DateTimeField中将默认使用属性read_only=True,如果不想使用此行为,需要显示对该字段进行声明:

class` `CommentSerializer(serializers.ModelSerializer):``  ``created ``=` `serializers.DateTimeField()` `  ``class` `Meta:``    ``model ``=` `Comment

6.FileField

对应models.FileField,代表一个文件,负责文件校验。

max_length:文件名最大长度;
allow_empty_file:是否允许为空文件;

7.ImageField

对应models.ImageField,代表一个图片,负责校验图片格式是否正确。

max_length:图片名最大长度;
allow_empty_file:是否允许为空文件;
如果要进行图片处理,推荐安装Pillow: pip install Pillow

8.HiddenField

这是serializers中特有的Field,它不根据用户提交获取值,而是从默认值或可调用的值中获取其值。一种常见的使用场景就是在Model中存在user_id作为外键,在用户提交时,不允许提交user_id,但user_id在定义Model时又是必须字段,这种情况下就可以使用HiddenField提供一个默认值:

class` `LeavingMessageSerializer(serializers.Serializer):` `  ``user ``=` `serializers.HiddenField(``    ``default``=``serializers.CurrentUserDefault()``  ``)

6.serializers.Field中的公共参数

所谓公共参数,是指对于所有的serializers.都可以接受的参数。以下是常见的一些公共参数。

1.read_only

read_only=True表示该字段为只读字段,即对应字段只用于序列化时(输出),而在反序列化时(创建对象)不使用该字段。默认值为False。

2.write_only

write_only=True表示该字段为只写字段,和read_only相反,即对应字段只用于更新或创建新的Model时,而在序列化时不使用,即不会输出给用户。默认值为False。

3.required

required=False表示对应字段在反序列化时是非必需的。在正常情况下,如果反序列化时缺少字段,则会抛出异常。默认值为True。

4.default

给字段指定一个默认值。需要注意,如果字段设置了default,则隐式地表示该字段已包含required=False,如果同时指定default和required,则会抛出异常。

5.allow_null

allow_null=True表示在序列化时允许None作为有效值。需要注意,如果没有显式使用default参数,则当指定allow_null=True时,在序列化过程中将会默认default=None,但并不会在反序列化时也默认。

6.validators

一个应用于传入字段的验证函数列表,如果验证失败,会引发验证错误,否则直接是返回,用于验证字段,如:

username ``=` `serializers.CharField(max_length``=``16``, required``=``True``, label``=``'用户名'``,``                   ``validators``=``[validators.UniqueValidator(queryset``=``User.objects.``all``(),message``=``'用户已经存在'``)]) 

7.error_message

验证时错误码和错误信息的一个dict,可以指定一些验证字段时的错误信息,如:

mobile``=` `serializers.CharField(max_length``=``4``, required``=``True``, write_only``=``True``, min_length``=``4``,``                 ``label``=``'电话'``, error_messages``=``{``                  ``'blank'``: ``'请输入验证码'``,``                  ``'required'``: ``'该字段必填项'``,``                  ``'max_length'``: ``'验证码格式错误'``,``                  ``'min_length'``: ``'验证码格式错误'``,``                ``})

7.style

一个键值对,用于控制字段如何渲染,最常用于对密码进行密文输入,如:

password ``=` `serializers.CharField(max_length``=``16``, min_length``=``6``, required``=``True``, label``=``'密码'``,``                  ``error_messages``=``{``                    ``'blank'``: ``'请输入密码'``,``                    ``'required'``: ``'该字段必填'``,``                    ``'max_length'``: ``'密码长度不超过16'``,``                    ``'min_length'``: ``'密码长度不小于6'``,` `                  ``},``                  ``style``=``{``'input_type'``: ``'password'``}, write_only``=``True``) 

9.label

一个简短的文本字串,用来描述该字段。

10.help_text

一个文本字串,可用作HTML表单字段或其他描述性元素中字段的描述。

11.allow_blank

allow_blank=True 可以为空 设置False则不能为空

12.source

source=‘user.email’(user表的email字段的值给这值) 设置字段值 类似default 通常这个值有外键关联属性可以用source设置

13.validators

验证该字段跟 单独的validate很像

UniqueValidator 单独唯一

validators=[UniqueValidator(queryset=UserProfile.objects.all())

UniqueTogetherValidator: 多字段联合唯一,这个时候就不能单独作用于某个字段,我们在Meta中设置。

validators = [UniqueTogetherValidator(queryset=UserFav.objects.all(),fields=(‘user’, ‘course’),message=‘已经收藏’)]

14.error_messages

错误消息提示

error_messages={
    "min_value": "商品数量不能小于一",
    "required": "请选择购买数量"
})

3.0.ModelSerializers

ModelSerializers继承于Serializer,相比其父类,ModelSerializer自动实现了以下三个步骤:

  • 1.根据指定的Model自动检测并生成序列化的字段,不需要提前定义;
  • 2.自动为序列化生成校验器;
  • 3.自动实现了create()方法和update()方法。

使用ModelSerializer方式如下:

class UserSerializer(serializers.ModelSerializer):
    # 1.独立校验器:重新设定字段, 替换掉模型中的设定, 重新设定地址的长度为5
    # address_validate是自定义的数据校验函数
    address = serializers.CharField(max_length=255, min_length=5, validators=
    [address_validate])

    # 2.单一字段验证(validate_字段名), 验证地址
    def validate_address(self, data):
        if data == '测试':
            raise serializers.ValidationError('请填写实际地址')  # 有错就抛出异常
        return data  # 没错就返回结果

    def validate_phone(self, data):
        # 不符合手机号格式
        # raise serializers.ValidationError('手机号格式不正确')
        model = self.root.Meta.model
        num = model.objects.filter(phone=data).count()
        if num > 0:
            raise serializers.ValidationError('手机号已存在')
        return data

    # 3.所有属性验证器
    def validate(self, attrs):
        # attrs:{"username":"zhangsan", "phone":"18538752511", ....}
        # 所有属性验证器
        # self.context 中有request和view上下文
        # self.context['view'].action 可以取到动作
        # attrs 是需要序列化的数据
        # raise serializers.ValidationError('xxx错误') # 有问题报错
        return attrs  # 没问题返回数据

    class Meta:
        model = User
        # fields = ('id', ) # 临时添加字段也需要写在这里
        fields = '__all__'  # 所有字段
        # exclude = ['id'] # 排除 id 字段
        read_only_fields = ('',)  # 指定字段为 read_only,
        # 扩展address: extra_kwargs = {} # 局部替换某些字段的设定, 或者新增设定
        extra_kwargs = {
            "address": {
                "min_length": 5,  # 给地址增加 最小长度限制
                "default": '默认测试地址',  # 增加默认值
            }
        }

相比于Serializer,可以说是简单了不少,当然,有时根据项目要求,可能也会在ModelSerializer中显示声明字段,这些在后面总结。

model

该属性指定一个Model类,ModelSerializer会根据提供的Model类自动检测出需要序列化的字段。默认情况下,所有Model类中的字段将会映射到ModelSerializer类中相应的字段。

fields

如果不希望对Model中所有的字符进行序列化,可以在fields属性中显示指定要进行序列化的字段。

你可能感兴趣的:(python,数据库,mysql)