序列化器补充
# 序列化器补充
# 常用序列化器字段
像模型的字段对应数据库字段类型一样,序列化器也有不同的字段类,用来对应不同的数据类型,在序列化,反序列化时进行类型转换和数据校验。
# CharField
文本字段,可以验证文本小于max_length
大于min_length
。
password = serializers.CharField(max_length=20, min_length=6)
# RegexField
文本字段,可以验证文本是否匹配给定正则表达式。
phone = serializers.RegexField(r'^1[3-9]\d{9}$')
# IntergerField
整数字段,可以验证整数小于max_value
,大于min_value
。
age = serializers.IntergerField(max_value=200, min_value=0)
# FloatField
实数字段,可以验证整数小于max_value
,大于min_value
。
salary = serializers.FloatField(min_value=0)
# DecimalField
高精度浮点数。
更多字段详见官方文档 (opens new window)
# 核心参数
每个序列化器字段类实例化时都会接收一些参数,一些字段还会接受额外的参数,下面的参数是字段核心参数,所有的字段类都支持。
# read_only
字段只读,默认值为False
。只读字段只会包含在序列化输出中,创建修改对象时不会包含该字段,即使输入了也会被忽略。
# write_only
字段只写,默认值为False
。和read_only
相反,序列化时不包含,创建修改对象时必须包含该字段。
# required
字段必须,默认值为True。必须字段在创建修改对象时必须包含,否则抛出异常。当设置为False时,在创建修改对象时可以不用包含该字段。
# default
默认值。如果一个字段设置了默认值,那么在反序列化时,如果没有提供该字段,则使用默认值进行填充。
在进行局部更新时,default
不会应用。因为局部更新时,只有更新的字段会被校验和返回。
还可以设置一个函数或者一个可调用对象,
可以设置为一个函数或其他可调用对象,在这种情况下,会使用调用后的结果进行填充。调用时,它将不接收任何参数。如果可调用对象有一个requires_context = True
的属性,那么序列化字段会被当做参数传入。例如:
class CurrentUserDefault:
"""
May be applied as a `default=...` value on a serializer field.
Returns the current user.
"""
requires_context = True
def __call__(self, serializer_field):
return serializer_field.context['request'].user
2
3
4
5
6
7
8
9
在序列化实例时,如果实例中不存在对象属性或字典键,将使用default的值填充。
注意,设置默认值意味着该字段不是必需的。同时包含默认和必需的关键字参数是无效的,将引发错误。
# allow_null
通常,如果将None传递给序列化器字段,将引发错误。如果None应该被认为是一个有效值,则将该关键字参数设置为True。
注意,如果没有显式的默认值,将该参数设置为True将意味着序列化输出的默认值为None,但这并不意味着输入反序列化是默认的。
默认值为False
# source
将用于填充字段的属性的名称。可以是一个只接受self参数的方法, 比如URLField(source='get_absolute_url')
,或者是一个句点法的属性,比如CharField(source='channel.name')
。
当使用句点法序列化字段时,如果在属性遍历期间没有任何对象或为空,则可能需要提供一个默认值。
默认值为字段的名称。
# validators
应该应用到输入字段的验证器函数的列表,它要么引发验证错误,要么简单地返回。验证器函数通常应该引发serializers.ValidationError
,但Django内置的ValidationError
也被支持,以便与Django或第三方Django包中定义的验证器兼容。
# error_messages
错误消息字典。
# label
一个短文本字符串,可以用作HTML表单字段或其他描述性元素中的字段名。
# help_text
可以在HTML表单字段或其他描述性元素中用作字段描述的文本字符串。
# 关系字段
关系字段用来表达模型关系。它们可以应用于ForeignKey, ManyToManyField和OneToOneField关系。
通常使用模型序列化器时,将自动生成序列化字段和关系。
# StringRelatedField
StringRelatedField
可以使用关系目标的__str__
方法来表示。
例如:
class StudentSerializer(serializers.ModelSerializer):
# 序列化后显示channel实例的__str__返回的值
channel = serializers.StringRelatedField()
class Meta:
model = Student
fields = '__all__'
2
3
4
5
6
7
8
序列化学生表示如下:
{
'id': 3,
'channel': '抖音',
'name': '赵六',
...
}
2
3
4
5
6
7
这个字段只读。
# 参数
many
-如果应用于一对多关系,则应该将此参数设置为True
。
# PrimaryKeyRelatedField
PrimaryKeyRelatedField
可以使用关系目标的主键来表示。
例如:
class StudentSerializer(serializers.ModelSerializer):
# 序列化后显示channel实例的__str__返回的值
channel = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Student
fields = '__all__'
2
3
4
5
6
7
序列化学生表示如下:
{
'id': 3,
'channel': 1,
'name': '赵六',
...
}
2
3
4
5
6
默认情况下,这个字段是可读写的,可以使用read_only设置为只读。
# 参数
queryset
- 验证字段输入时用于模型实例查找的queryset。关系必须显式设置一个queryset,或者设置read_only=True。many
- 如果应用于一对多关系,则应该将此参数设置为True
。allow_null
- 如果设置为True,该字段将接受None的值或空字符串的可空关系。默认是Falsepk_field
- 设置为一个字段来控制对主键值的序列化/反序列化。
# HyperlinkedRelatedField
HyperlinkedRelatedField
使用一个超链接来表示关系目标。
例如:
class StudentSerializer(serializers.ModelSerializer):
channel = serializers.HyperlinkedRelatedField(read_only=True, view_name='channel-detail')
class Meta:
model = Student
fields = '__all__'
2
3
4
5
6
序列化学生表示如下:
{
'id': 3,
'channel': 'http://127.0.0.1:8000/channel/1/',
'name': '赵六',
...
}
2
3
4
5
6
默认情况下,这个字段是可读写的,可以使用read_only设置为只读。
注意:该字段是为映射到一个URL的对象设计的,该URL接受一个URL关键字参数,使用lookup_field和lookup_url_kwarg参数设置。
这仅适用于URL中包含一个主键或slug参数的URL。
# 参数
view_name
- 关系对象的视图名称。这个参数是必须的。
queryset
- 验证字段输入时用于模型实例查找的queryset。关系必须显式设置一个queryset,或者设置read_only=True。
many
- 如果应用于一对多关系,则应该将此参数设置为True
。
allow_null
- 如果设置为True,该字段将接受None的值或空字符串的可空关系。默认是False
lookup_field
- 应用于查询的字段。应该对应于被引用视图上的URL关键字参数。默认为pk
lookup_url_kwarg
- URL配置文件中定义的关键字参数的名称,对应于查找字段。默认使用与lookup_field相同的值。
format
- 如果使用格式后缀,超链接字段将为目标使用相同的格式后缀,除非使用format参数重写。
# SlugRelatedField
SlugRelatedField
使用目标上的某个字段来表示关系。
例如:
class StudentSerializer(serializers.ModelSerializer):
channel = serializers.SlugRelatedField(read_only=True, slug_field='name')
class Meta:
model = Student
fields = '__all__'
2
3
4
5
6
序列化学生表示如下:
{
'id': 3,
'channel': '抖音',
'name': '赵六',
...
}
2
3
4
5
6
默认情况下,这个字段是可读写的,可以使用read_only设置为只读。
当使用SlugRelatedField作为读写字段时,您通常需要确保slug字段对应的模型字段设置了unique=True
。
# 参数
slug_field
- 目标上应该用来表示它的字段。这应该是唯一标识任何给定实例的字段。这应该是必须的。
queryset
- 验证字段输入时用于模型实例查找的queryset。关系必须显式设置一个queryset,或者设置read_only=True。
many
- 如果应用于一对多关系,则应该将此参数设置为True
。
allow_null
- 如果设置为True,该字段将接受None的值或空字符串的可空关系。默认是False
# 嵌套关系
序列化器还可以进行嵌套表示。例如:
class ChannelSerializer(serializers.ModelSerializer):
class Meta:
model = Channel
fields = '__all__'
class StudentSerializer(serializers.ModelSerializer):
qq = serializers.CharField(allow_blank=True, allow_null=True, help_text='qq号码', label='Qq号码', max_length=20, required=False,
validators=[ UniqueValidator(queryset=Student.objects.all())],
error_messages={
'max_length': 'qq号码长度大于20位'
})
phone = serializers.RegexField(r'^1[3-9]\d{9}$',allow_blank=True, allow_null=True, help_text='手机号码', label='手机号码', max_length=11, min_length=11, required
=False, validators=[ UniqueValidator(queryset=Student.objects.all())])
channel = ChannelSerializer(read_only=True)
# 元信息
class Meta:
# 指定根据哪个模型生成序列化器
model = Student
# 指定序列化哪些字段
# fields = ['id', 'name', 'sex']
# 所有字段
fields = '__all__'
# fields = ['id', 'name', 'channel_name']
# 排除
# exclude = ['id']
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 模型序列化器
# 检查一个模型序列化器
直接打印模型序列化器的实例
# 指定包含字段
fields = ['id', 'account_name', 'users', 'created'] # 显示指定
fields = '__all__' # 所有字段
exclude = ['users'] # 排除字段
2
3
4
# 指定内嵌序列化
默认的ModelSerializer使用主键作为关系,但你也可以使用depth选项轻松地生成嵌套表示:
class StudentSerializer(serializers.ModelSerializer):
...
class Meta:
model = Student
fields = '__all__'
depth = 1
2
3
4
5
6
应该将depth选项设置为一个整数值,表示嵌套的深度。如果想要自定义序列化的方式,需要自己定义字段。
# 显示指定额外字段
你可以通过在类上声明字段来向ModelSerializer添加额外的字段,或者覆盖默认字段,就像定义普通的Serializer类一样。
class StudentSerializer(serializers.ModelSerializer):
channel_name = serializers.CharField(source='channel.name')
class Meta:
model = Student
fields = '__all__'
2
3
4
5
# 指定只读字段
如果希望将多个字段指定为只读。你可以使用快捷的Meta选项read_only_fields,而不是使用read_only=True属性显式地添加每个字段。
class StudentSerializer(serializers.ModelSerializer):
channel_name = serializers.CharField(source='channel.name')
class Meta:
model = Student
fields = '__all__'
read_only_fields = ['channel_name']
2
3
4
5
6
# 额外的关键字参数
还有一个快捷方式,允许你使用extra_kwargs选项在字段上指定任意额外的关键字参数。与read_only_fields的情况一样,这意味着你不需要在序列化器上显式声明该字段。这个选项是一个字典,将字段名映射到关键字参数的字典。例如:
class StudentSerializer(serializers.ModelSerializer):
...
# channel = ChannelSerializer(read_only=True)
# 元信息
class Meta:
# 指定根据哪个模型生成序列化器
model = Student
# 指定序列化哪些字段
# fields = ['id', 'name', 'sex']
# 所有字段
fields = '__all__'
extra_kwargs = {
'qq': {'error_messages':{'max_length':'qq号码长度大于20位'}}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 反序列化校验
反序列化数据时,始终需要在尝试访问已验证数据或保存对象实例之前调用is_valid()
。如果发生任何验证错误,序列化器对象的.errors
属性将包含一个字典,表示生成的错误消息。
{'phone': [ErrorDetail(string='请确保这个字段至少包含 11 个字符。', code='min_length'), ErrorDetail(string='输
入值不匹配要求的模式。', code='invalid')]}
2
字典中的每个键都将是字段名称,值将是与该字段对应的任何错误消息的字符串列表。non_field_errors
将列出任何一般验证错误。
# 字段级验证
可以通过向子类添加.validate_<field_name>
方法来指定自定义字段级验证。这些方法采用单个参数,即需要验证的字段值。validate_<field_name>
方法应该返回经过验证的值或引发serializers.ValidationError
. 例如:
class StudentSerializer(serializers.ModelSerializer):
...
def validate_phone(self, value):
if not re.match(r'^1[3-9]\d{9}$', value):
raise serializers.ValidationError('请输入正确的手机号码!')
return value
class Meta:
model = Student
fields = '__all__'
2
3
4
5
6
7
8
9
10
11
12
如果<field_name>
在序列化程序上声明了参数required=False
,如果不包含该字段,则不会执行此验证步骤。
# 对象级验证
要执行需要访问多个字段的任何其他验证,请添加一个调用.validate()
到你的Serializer
子类的方法。此方法采用单个参数,即字段值字典
class StudentSerializer(serializers.ModelSerializer):
...
def validate(self, data):
if not (data['phone'] and data['qq']):
raise serializer.ValidationError('请同时提供qq和电话号码')
return data
class Meta:
model = Student
fields = '__all__'
2
3
4
5
6
7
8
9
10
# 验证器
序列化器上的各个字段还可以包含验证器,方法是在字段实例上声明它们,例如:
def validate_phone(value):
if not re.match(r'^1[3-9]\d{9}$', value):
raise serializers.ValidationError('请输入正确的手机号码!')
class StudentSerializer(serializers.ModelSerializer):
phone = serializers.CharField(validators=[validate_phone])
2
3
4
5
6
序列化程序类还可以包括应用于完整字段数据集的可重用验证器。这些验证器通过在内部Meta
类中声明它们来包含,如下所示:
class EventSerializer(serializers.Serializer):
name = serializers.CharField()
room_number = serializers.IntegerField(choices=[101, 102, 103, 201])
date = serializers.DateField()
class Meta:
# Each room only has one event per day.
validators = [
UniqueTogetherValidator(
queryset=Event.objects.all(),
fields=['room_number', 'date']
)
]
2
3
4
5
6
7
8
9
10
11
12
13
有关更多信息,请参阅验证器文档 (opens new window)。
本文完,感谢你的耐心阅读,如有需要可加我微信,备注「博客」并说明原因,我们一起进步,下次见。
