序列化器字段
Form 类中的每个字段不仅负责验证数据,还负责“清理”数据,即将其规范化为一致的格式。
序列化字段处理在原始值和内部数据类型之间的转换。它们还处理验证输入值,以及从其父对象中检索和设置值。
注意:序列化字段在 fields.py
中声明,但按照惯例,你应该使用 from rest_framework import serializers
导入它们,并将字段称为 serializers.<FieldName>
。
核心参数
每个序列化字段类构造函数至少接受这些参数。一些字段类接受其他字段特定的参数,但以下参数始终应被接受
read_only
只读字段包含在 API 输出中,但不应该包含在创建或更新操作期间的输入中。任何错误包含在序列化器输入中的“只读”字段都将被忽略。
将其设置为 True
以确保在序列化表示形式时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。
默认为 False
write_only
将其设置为 True
以确保在更新或创建实例时可以使用该字段,但在序列化表示形式时不包含该字段。
默认为 False
required
通常,如果反序列化期间未提供字段,则会引发错误。如果反序列化期间不需要此字段,则设置为 false。
将此项设为 False
还允许在序列化实例时省略对象属性或字典键。如果键不存在,它将不会包含在输出表示中。
默认为 True
。如果您正在使用 模型序列化器,如果您在 Model
中的字段中指定了 blank=True
或 default
或 null=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
在序列化实例时,如果实例中不存在对象属性或字典键,则将使用 default。
请注意,设置 default
值意味着该字段不是必需的。同时包含 default
和 required
关键字参数是无效的,并且会引发错误。
allow_null
通常,如果将 None
传递给序列化器字段,则会引发错误。如果 None
应被视为有效值,请将此关键字参数设置为 True
。
请注意,如果没有明确的 default
,将此参数设置为 True
将暗示序列化输出的 default
值为 null
,但并不暗示输入反序列化的 default
值。
默认为 False
source
将用于填充字段的属性的名称。可以是仅采用 self
参数的方法,例如 URLField(source='get_absolute_url')
,也可以使用点号表示法来遍历属性,例如 EmailField(source='user.email')
。
使用点号表示法序列化字段时,如果在属性遍历期间任何对象不存在或为空,则可能需要提供 default
值。如果您正在访问关系 orm 模型,请当心使用 source 属性时可能存在的 n+1 问题。例如
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField(source="user.email")
当未预取时,此情况需要从数据库中获取用户对象。如果不需要这样做,请务必适当地使用 prefetch_related
和 select_related
方法。有关这些方法的更多信息,请参阅 django 文档。
值 source='*'
具有特殊含义,用于指示应将整个对象传递到该字段。这对于创建嵌套表示或对于需要访问完整对象才能确定输出表示的字段非常有用。
默认为字段的名称。
验证器
应应用于传入字段输入的一系列验证器函数,这些函数要么引发验证错误,要么直接返回。验证器函数通常应引发 serializers.ValidationError
,但 Django 内置的 ValidationError
也受支持,以便与 Django 代码库或第三方 Django 包中定义的验证器兼容。
错误消息
错误代码到错误消息的字典。
标签
一个短文本字符串,可用作 HTML 表单字段或其他描述性元素中的字段名称。
帮助文本
一个文本字符串,可用作 HTML 表单字段或其他描述性元素中的字段描述。
初始值
一个值,应用于预填充 HTML 表单字段的值。你可以向其传递一个可调用对象,就像你可以对任何常规 Django Field
所做的那样。
import datetime
from rest_framework import serializers
class ExampleSerializer(serializers.Serializer):
day = serializers.DateField(initial=datetime.date.today)
样式
一个键值对字典,可用于控制渲染器如何渲染字段。
这里有两个示例:'input_type'
和 'base_template'
# Use <input type="password"> for the input.
password = serializers.CharField(
style={'input_type': 'password'}
)
# Use a radio input instead of a select input.
color_channel = serializers.ChoiceField(
choices=['red', 'green', 'blue'],
style={'base_template': 'radio.html'}
)
有关更多详细信息,请参阅 HTML 和表单 文档。
布尔字段
BooleanField
一个布尔表示形式。
使用 HTML 编码的表单输入时,请注意,即使指定了 default=True
选项,省略值始终会被视为将字段设置为 False
。这是因为 HTML 复选框输入通过省略值来表示未选中状态,因此 REST 框架将省略视为它是一个空的复选框输入。
请注意,Django 2.1 从 models.BooleanField
中删除了 blank
kwarg。在 Django 2.1 之前,models.BooleanField
字段始终为 blank=True
。因此,自 Django 2.1 以来,默认的 serializers.BooleanField
实例将生成而不带 required
kwarg(即等效于 required=True
),而对于以前版本的 Django,默认的 BooleanField
实例将使用 required=False
选项生成。如果你想手动控制此行为,请在序列化程序类中显式声明 BooleanField
,或使用 extra_kwargs
选项设置 required
标志。
对应于 django.db.models.fields.BooleanField
。
签名:BooleanField()
字符串字段
CharField
一个文本表示形式。选择性地验证文本是否短于 max_length
且长于 min_length
。
对应于 django.db.models.fields.CharField
或 django.db.models.fields.TextField
。
签名:CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
max_length
- 验证输入不包含超过此数量的字符。min_length
- 验证输入不包含少于此数量的字符。allow_blank
- 如果设置为True
,则空字符串应被视为有效值。如果设置为False
,则空字符串被视为无效值,并将引发验证错误。默认为False
。trim_whitespace
- 如果设置为True
,则修剪前导和尾随空格。默认为True
。
allow_null
选项也适用于字符串字段,尽管不鼓励使用它,而赞成使用 allow_blank
。同时设置 allow_blank=True
和 allow_null=True
是有效的,但这样做意味着字符串表示形式将允许两种不同类型的空值,这可能导致数据不一致和微妙的应用程序错误。
EmailField
一个文本表示形式,验证文本是否为有效的电子邮件地址。
对应于 django.db.models.fields.EmailField
签名: EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField
文本表示,验证给定值是否与某个正则表达式匹配。
对应于 django.forms.fields.RegexField
。
签名: RegexField(regex, max_length=None, min_length=None, allow_blank=False)
必需的 regex
参数可以是字符串,也可以是已编译的 Python 正则表达式对象。
使用 Django 的 django.core.validators.RegexValidator
进行验证。
SlugField
一个 RegexField
,用于针对模式 [a-zA-Z0-9_-]+
验证输入。
对应于 django.db.models.fields.SlugField
。
签名: SlugField(max_length=50, min_length=None, allow_blank=False)
URLField
一个 RegexField
,用于针对 URL 匹配模式验证输入。期望完全限定的 URL,格式为 http://<host>/<path>
。
对应于 django.db.models.fields.URLField
。使用 Django 的 django.core.validators.URLValidator
进行验证。
签名: URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField
一个字段,用于确保输入是有效的 UUID 字符串。to_internal_value
方法将返回一个 uuid.UUID
实例。在输出时,该字段将返回一个采用规范连字符格式的字符串,例如
"de305d54-75b4-431b-adb2-eb6b9e546013"
签名: UUIDField(format='hex_verbose')
format
:确定 uuid 值的表示格式'hex_verbose'
- 规范十六进制表示形式,包括连字符:"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
'hex'
- UUID 的紧凑十六进制表示形式,不包括连字符:"5ce0e9a55ffa654bcee01238041fb31a"
'int'
- UUID 的 128 位整数表示形式:"123456789012312313134124512351145145114"
'urn'
- UUID 的 RFC 4122 URN 表示形式:"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
更改format
参数仅影响表示值。to_internal_value
接受所有格式
FilePathField
一个字段,其选项仅限于文件系统上某个目录中的文件名
对应于 django.forms.fields.FilePathField
。
签名: FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)
path
- FilePathField 应从中获取其选项的目录的绝对文件系统路径。match
- FilePathField 将用作字符串的正则表达式,用于过滤文件名。recursive
- 指定是否应包括 path 的所有子目录。默认值为False
。allow_files
- 指定是否应包含指定位置中的文件。默认值为True
。此项或allow_folders
必须为True
。allow_folders
- 指定是否应包含指定位置中的文件夹。默认值为False
。此项或allow_files
必须为True
。
IPAddressField
确保输入为有效 IPv4 或 IPv6 字符串的字段。
对应于 django.forms.fields.IPAddressField
和 django.forms.fields.GenericIPAddressField
。
签名:IPAddressField(protocol='both', unpack_ipv4=False, **options)
protocol
将有效输入限制为指定协议。接受的值为“both”(默认值)、“IPv4”或“IPv6”。匹配不区分大小写。unpack_ipv4
解包 IPv4 映射地址,如 ::ffff:192.0.2.1。如果启用此选项,该地址将解包为 192.0.2.1。默认情况下禁用。仅当协议设置为“both”时才能使用。
数字字段
IntegerField
整数表示。
对应于 django.db.models.fields.IntegerField
、django.db.models.fields.SmallIntegerField
、django.db.models.fields.PositiveIntegerField
和 django.db.models.fields.PositiveSmallIntegerField
。
签名:IntegerField(max_value=None, min_value=None)
max_value
验证提供的数字不超过此值。min_value
验证提供的数字不小于此值。
FloatField
浮点表示。
对应于 django.db.models.fields.FloatField
。
签名:FloatField(max_value=None, min_value=None)
max_value
验证提供的数字不超过此值。min_value
验证提供的数字不小于此值。
DecimalField
十进制表示,在 Python 中由 Decimal
实例表示。
对应于 django.db.models.fields.DecimalField
。
签名:DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
max_digits
数字中允许的最大位数。它必须是None
或大于或等于decimal_places
的整数。decimal_places
要与数字一起存储的小数位数。coerce_to_string
如果应为表示形式返回字符串值,则设置为True
,如果应返回Decimal
对象,则设置为False
。默认为与COERCE_DECIMAL_TO_STRING
设置键相同的值,除非被覆盖,否则该值为True
。如果序列化程序返回Decimal
对象,则最终输出格式将由渲染器确定。请注意,设置localize
将强制该值变为True
。max_value
验证提供的数字不超过此值。min_value
验证提供的数字不小于此值。localize
设置为True
以根据当前语言环境启用输入和输出的本地化。这还将强制coerce_to_string
变为True
。默认为False
。请注意,如果您在设置文件中设置了USE_L10N=True
,则会启用数据格式化。rounding
设置量化到配置精度时使用的舍入模式。有效值是decimal
模块舍入模式。默认为None
。normalize_output
序列化时将对十进制值进行规范化。这将去除所有尾随零,并将值精度更改为能够表示值而不会丢失数据的最小所需精度。默认为False
。
示例用法
要验证精度为 2 位小数的 999 以下的数字,可以使用
serializers.DecimalField(max_digits=5, decimal_places=2)
要验证精度为 10 位小数的十亿以下的数字
serializers.DecimalField(max_digits=19, decimal_places=10)
日期和时间字段
DateTimeField
日期和时间表示形式。
对应于 django.db.models.fields.DateTimeField
。
签名: DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None, default_timezone=None)
format
- 表示输出格式的字符串。如果未指定,这将默认为与DATETIME_FORMAT
设置键相同的值,除非设置,否则为'iso-8601'
。设置为格式字符串表示to_representation
返回值应强制转换为字符串输出。格式字符串如下所述。将此值设置为None
表示to_representation
应返回 Pythondatetime
对象。在这种情况下,日期时间编码将由渲染器确定。input_formats
- 表示可用于解析日期的输入格式的字符串列表。如果未指定,将使用DATETIME_INPUT_FORMATS
设置,其默认为['iso-8601']
。default_timezone
- 表示时区的tzinfo
子类(zoneinfo
或pytz
)。如果未指定且启用了USE_TZ
设置,这将默认为 当前时区。如果禁用了USE_TZ
,则日期时间对象将是朴素的。
DateTimeField
格式字符串。
格式字符串可以是明确指定格式的 Python strftime 格式,也可以是特殊字符串 'iso-8601'
,表示应使用 ISO 8601 样式的日期时间。(例如 '2013-01-29T12:34:56.000000Z'
)
当格式的 None
值用于 datetime
对象时,将由 to_representation
返回,最终输出表示形式将由渲染器类确定。
auto_now
和 auto_now_add
模型字段。
使用 ModelSerializer
或 HyperlinkedModelSerializer
时,请注意任何具有 auto_now=True
或 auto_now_add=True
的模型字段将使用默认情况下为 read_only=True
的序列化器字段。
如果你想覆盖此行为,则需要在序列化器上显式声明 DateTimeField
。例如
class CommentSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField()
class Meta:
model = Comment
DateField
日期表示。
对应于 django.db.models.fields.DateField
签名:DateField(format=api_settings.DATE_FORMAT, input_formats=None)
format
- 表示输出格式的字符串。如果未指定,则默认为与DATE_FORMAT
设置键相同的值,除非设置,否则该值为'iso-8601'
。设置为格式字符串表示to_representation
返回值应强制转换为字符串输出。格式字符串如下所述。将此值设置为None
表示 Pythondate
对象应由to_representation
返回。在这种情况下,日期编码将由渲染器确定。input_formats
- 表示可用于解析日期的输入格式的字符串列表。如果未指定,则将使用DATE_INPUT_FORMATS
设置,其默认为['iso-8601']
。
DateField
格式字符串
格式字符串可以是 Python strftime 格式,它明确指定格式,或特殊字符串 'iso-8601'
,表示应使用 ISO 8601 样式的日期。(例如 '2013-01-29'
)
TimeField
时间表示。
对应于 django.db.models.fields.TimeField
签名:TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
format
- 表示输出格式的字符串。如果未指定,则默认为与TIME_FORMAT
设置键相同的值,除非设置,否则该值为'iso-8601'
。设置为格式字符串表示to_representation
返回值应强制转换为字符串输出。格式字符串如下所述。将此值设置为None
表示 Pythontime
对象应由to_representation
返回。在这种情况下,时间编码将由渲染器确定。input_formats
- 表示可用于解析日期的输入格式的字符串列表。如果未指定,将使用TIME_INPUT_FORMATS
设置,其默认值为['iso-8601']
。
TimeField
格式字符串
格式字符串可以是 Python strftime 格式,它明确指定格式,或特殊字符串 'iso-8601'
,表示应使用 ISO 8601 样式时间。(例如 '12:34:56.000000'
)
DurationField
持续时间表示形式。对应于 django.db.models.fields.DurationField
这些字段的 validated_data
将包含一个 datetime.timedelta
实例。表示形式是一个遵循以下格式的字符串 '[DD] [HH:[MM:]]ss[.uuuuuu]'
。
签名: DurationField(max_value=None, min_value=None)
max_value
验证提供的持续时间不大于此值。min_value
验证提供的持续时间不小于此值。
选择字段
ChoiceField
一个可以接受有限选择值集中的值的字段。
如果相应的模型字段包含 choices=…
参数,则 ModelSerializer
使用它来自动生成字段。
签名: ChoiceField(choices)
choices
- 有效值列表,或(key, display_name)
元组列表。allow_blank
- 如果设置为True
,则空字符串应被视为有效值。如果设置为False
,则空字符串被视为无效值,并将引发验证错误。默认为False
。html_cutoff
- 如果设置,这将是 HTML 选择下拉菜单显示的最大选择数。可用于确保具有非常大可能选择的自动生成的 ChoiceField 不会阻止模板呈现。默认为None
。html_cutoff_text
- 如果设置,如果 HTML 选择下拉菜单中已截断最大项目数,这将显示文本指示符。默认为"More than {count} items…"
allow_blank
和 allow_null
都是 ChoiceField
上的有效选项,但强烈建议只使用一个,而不是同时使用。对于文本选择,应首选 allow_blank
,对于数字或其他非文本选择,应首选 allow_null
。
MultipleChoiceField
一个可以接受一组零、一或多个值(从有限的选择集中选取)的字段。采用一个单一强制参数。to_internal_value
返回一个包含所选值的 set
。
签名: MultipleChoiceField(choices)
choices
- 有效值列表,或(key, display_name)
元组列表。allow_blank
- 如果设置为True
,则空字符串应被视为有效值。如果设置为False
,则空字符串被视为无效值,并将引发验证错误。默认为False
。html_cutoff
- 如果设置,这将是 HTML 选择下拉菜单显示的最大选择数。可用于确保具有非常大可能选择的自动生成的 ChoiceField 不会阻止模板呈现。默认为None
。html_cutoff_text
- 如果设置,如果 HTML 选择下拉菜单中已截断最大项目数,这将显示文本指示符。默认为"More than {count} items…"
与 ChoiceField
一样,allow_blank
和 allow_null
选项都是有效的,但强烈建议只使用一个,而不是同时使用。对于文本选择,应首选 allow_blank
,对于数字或其他非文本选择,应首选 allow_null
。
文件上传字段
解析器和文件上传。
FileField
和 ImageField
类仅适用于 MultiPartParser
或 FileUploadParser
。大多数解析器(例如 JSON)不支持文件上传。Django 的常规 FILE_UPLOAD_HANDLERS 用于处理上传的文件。
FileField
文件表示形式。执行 Django 的标准 FileField 验证。
对应于 django.forms.fields.FileField
。
签名:FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
max_length
- 指定文件名的最大长度。allow_empty_file
- 指定是否允许空文件。use_url
- 如果设置为True
,则 URL 字符串值将用于输出表示形式。如果设置为False
,则文件名字符串值将用于输出表示形式。默认为UPLOADED_FILES_USE_URL
设置键的值,除非另有设置,否则该值为True
。
ImageField
图像表示形式。验证上传的文件内容是否与已知图像格式匹配。
对应于 django.forms.fields.ImageField
。
签名:ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
max_length
- 指定文件名的最大长度。allow_empty_file
- 指定是否允许空文件。use_url
- 如果设置为True
,则 URL 字符串值将用于输出表示形式。如果设置为False
,则文件名字符串值将用于输出表示形式。默认为UPLOADED_FILES_USE_URL
设置键的值,除非另有设置,否则该值为True
。
需要 Pillow
包或 PIL
包。推荐使用 Pillow
包,因为 PIL
不再积极维护。
复合字段
ListField
验证对象列表的字段类。
签名:ListField(child=<A_FIELD_INSTANCE>, allow_empty=True, min_length=None, max_length=None)
child
- 用于验证列表中对象的字段实例。如果未提供此参数,则不会验证列表中的对象。allow_empty
- 指定是否允许空列表。min_length
- 验证列表中元素的数量不低于此数字。max_length
- 验证列表中元素的数量不高于此数字。
例如,要验证整数列表,可以使用类似以下内容
scores = serializers.ListField(
child=serializers.IntegerField(min_value=0, max_value=100)
)
ListField
类还支持允许编写可重复使用的列表字段类的声明式样式。
class StringListField(serializers.ListField):
child = serializers.CharField()
现在,我们可以在整个应用程序中重复使用自定义 StringListField
类,而无需向其提供 child
参数。
DictField
验证对象字典的字段类。DictField
中的键始终假定为字符串值。
签名:DictField(child=<A_FIELD_INSTANCE>, allow_empty=True)
child
- 用于验证字典中值的字段实例。如果未提供此参数,则不会验证映射中的值。allow_empty
- 指定是否允许空字典。
例如,要创建一个验证字符串到字符串的映射的字段,可以编写类似以下内容
document = DictField(child=CharField())
还可以使用声明式样式,如 ListField
。例如
class DocumentField(DictField):
child = CharField()
HStoreField
与 Django 的 postgres HStoreField
兼容的预配置 DictField
。
签名:HStoreField(child=<A_FIELD_INSTANCE>, allow_empty=True)
child
- 用于验证字典中值的字段实例。默认子字段接受空字符串和空值。allow_empty
- 指定是否允许空字典。
请注意,子字段必须是 CharField
的实例,因为 hstore 扩展将值存储为字符串。
JSONField
一个字段类,用于验证传入的数据结构是否包含有效的 JSON 原语。在其备用二进制模式中,它将表示和验证 JSON 编码的二进制字符串。
签名:JSONField(binary, encoder)
binary
- 如果设置为True
,则该字段将输出并验证 JSON 编码的字符串,而不是原始数据结构。默认为False
。encoder
- 使用此 JSON 编码器序列化输入对象。默认为None
。
其他字段
ReadOnlyField
一个字段类,它简单地返回字段的值,而不进行修改。
在包含与属性而不是模型字段相关的字段名称时,此字段在使用 ModelSerializer
时默认使用。
签名:ReadOnlyField()
例如,如果 has_expired
是 Account
模型上的一个属性,那么以下序列化器将自动将其生成为 ReadOnlyField
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ['id', 'account_name', 'has_expired']
HiddenField
一个字段类,它不根据用户输入获取值,而是从默认值或可调用对象获取值。
签名:HiddenField()
例如,要包含一个字段,该字段始终提供当前时间作为序列化器验证数据的一部分,可以使用以下内容
modified = serializers.HiddenField(default=timezone.now)
通常只有在需要根据一些预先提供的字段值运行一些验证,但又不希望向最终用户公开所有这些字段时,才需要 HiddenField
类。
有关 HiddenField
的更多示例,请参阅验证器文档。
注意: HiddenField()
不出现在 partial=True
序列化器中(在进行 PATCH
请求时)。此行为将来可能会更改,请关注github 讨论中的更新。
ModelField
一个通用字段,可以绑定到任何任意模型字段。ModelField
类将序列化/反序列化任务委派给其关联的模型字段。此字段可用于为自定义模型字段创建序列化器字段,而无需创建新的自定义序列化器字段。
ModelSerializer
使用此字段来对应于自定义模型字段类。
签名: ModelField(model_field=<Django 模型字段实例>)
ModelField
类通常用于内部使用,但如果需要,您的 API 也可以使用它。为了正确实例化 ModelField
,必须向其传递附加到实例化模型的字段。例如:ModelField(model_field=MyModel()._meta.get_field('custom_field'))
SerializerMethodField
这是一个只读字段。它通过调用附加到它的序列化器类上的方法来获取其值。它可用于向对象的序列化表示中添加任何类型的数据。
签名:SerializerMethodField(method_name=None)
method_name
- 要调用的序列化器上的方法的名称。如果未包含,则默认为get_<field_name>
。
method_name
参数引用的序列化器方法应接受一个参数(除了 self
之外),即正在序列化的对象。它应该返回您希望包含在对象的序列化表示中的任何内容。例如
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
fields = '__all__'
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
自定义字段
如果您想创建一个自定义字段,则需要对 Field
进行子类化,然后覆盖 .to_representation()
和 .to_internal_value()
方法中的一个或两个。这两个方法用于在初始数据类型和原始可序列化数据类型之间进行转换。原始数据类型通常是数字、字符串、布尔值、date
/time
/datetime
或 None
。它们还可以是任何列表或字典之类的对象,其中仅包含其他原始对象。根据您使用的渲染器,还可能支持其他类型。
调用 .to_representation()
方法将初始数据类型转换为原始可序列化数据类型。
调用 .to_internal_value()
方法将原始数据类型还原为其内部 python 表示形式。如果数据无效,此方法应引发 serializers.ValidationError
。
示例
基本自定义字段
我们来看一个序列化表示 RGB 颜色值的类的示例
class Color:
"""
A color represented in the RGB colorspace.
"""
def __init__(self, red, green, blue):
assert(red >= 0 and green >= 0 and blue >= 0)
assert(red < 256 and green < 256 and blue < 256)
self.red, self.green, self.blue = red, green, blue
class ColorField(serializers.Field):
"""
Color objects are serialized into 'rgb(#, #, #)' notation.
"""
def to_representation(self, value):
return "rgb(%d, %d, %d)" % (value.red, value.green, value.blue)
def to_internal_value(self, data):
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
return Color(red, green, blue)
默认情况下,字段值被视为映射到对象上的属性。如果您需要自定义字段值的访问和设置方式,则需要覆盖 .get_attribute()
和/或 .get_value()
。
例如,我们创建一个字段,该字段可用于表示正在序列化的对象的类名
class ClassNameField(serializers.Field):
def get_attribute(self, instance):
# We pass the object instance onto `to_representation`,
# not just the field attribute.
return instance
def to_representation(self, value):
"""
Serialize the value's class name.
"""
return value.__class__.__name__
引发验证错误
我们上面的 ColorField
类当前不执行任何数据验证。为了指示无效数据,我们应该引发 serializers.ValidationError
,如下所示
def to_internal_value(self, data):
if not isinstance(data, str):
msg = 'Incorrect type. Expected a string, but got %s'
raise ValidationError(msg % type(data).__name__)
if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
raise ValidationError('Incorrect format. Expected `rgb(#,#,#)`.')
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
if any([col > 255 or col < 0 for col in (red, green, blue)]):
raise ValidationError('Value out of range. Must be between 0 and 255.')
return Color(red, green, blue)
.fail()
方法是引发 ValidationError
的快捷方式,它从 error_messages
字典中获取消息字符串。例如
default_error_messages = {
'incorrect_type': 'Incorrect type. Expected a string, but got {input_type}',
'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.',
'out_of_range': 'Value out of range. Must be between 0 and 255.'
}
def to_internal_value(self, data):
if not isinstance(data, str):
self.fail('incorrect_type', input_type=type(data).__name__)
if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
self.fail('incorrect_format')
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
if any([col > 255 or col < 0 for col in (red, green, blue)]):
self.fail('out_of_range')
return Color(red, green, blue)
这种样式使您的错误消息更简洁,与您的代码更分离,并且应该是首选。
使用 source='*'
这里我们将举一个具有 x_coordinate
和 y_coordinate
属性的扁平 DataPoint
模型的示例。
class DataPoint(models.Model):
label = models.CharField(max_length=50)
x_coordinate = models.SmallIntegerField()
y_coordinate = models.SmallIntegerField()
使用自定义字段和 source='*'
,我们可以提供坐标对的嵌套表示
class CoordinateField(serializers.Field):
def to_representation(self, value):
ret = {
"x": value.x_coordinate,
"y": value.y_coordinate
}
return ret
def to_internal_value(self, data):
ret = {
"x_coordinate": data["x"],
"y_coordinate": data["y"],
}
return ret
class DataPointSerializer(serializers.ModelSerializer):
coordinates = CoordinateField(source='*')
class Meta:
model = DataPoint
fields = ['label', 'coordinates']
请注意,此示例不处理验证。部分原因是,在实际项目中,坐标嵌套可以使用嵌套序列化器来更好地处理,方法是使用 source='*'
,以及两个 IntegerField
实例,每个实例都有自己的 source
指向相关字段。
然而,此示例中的要点是
-
to_representation
传递整个DataPoint
对象,并且必须从该对象映射到所需的输出。>>> instance = DataPoint(label='Example', x_coordinate=1, y_coordinate=2) >>> out_serializer = DataPointSerializer(instance) >>> out_serializer.data ReturnDict([('label', 'Example'), ('coordinates', {'x': 1, 'y': 2})])
-
除非我们的字段为只读,否则
to_internal_value
必须映射回一个适合更新我们的目标对象的字典。使用source='*'
,to_internal_value
的返回值将更新根验证数据字典,而不是单个键。>>> data = { ... "label": "Second Example", ... "coordinates": { ... "x": 3, ... "y": 4, ... } ... } >>> in_serializer = DataPointSerializer(data=data) >>> in_serializer.is_valid() True >>> in_serializer.validated_data OrderedDict([('label', 'Second Example'), ('y_coordinate', 4), ('x_coordinate', 3)])
为了完整起见,让我们再次执行相同操作,但使用上面建议的嵌套序列化器方法
class NestedCoordinateSerializer(serializers.Serializer):
x = serializers.IntegerField(source='x_coordinate')
y = serializers.IntegerField(source='y_coordinate')
class DataPointSerializer(serializers.ModelSerializer):
coordinates = NestedCoordinateSerializer(source='*')
class Meta:
model = DataPoint
fields = ['label', 'coordinates']
此处,目标和源属性对(x
和 x_coordinate
,y
和 y_coordinate
)之间的映射在 IntegerField
声明中进行处理。是我们的 NestedCoordinateSerializer
采用了 source='*'
。
我们的新 DataPointSerializer
表现出与自定义字段方法相同的行为。
序列化
>>> out_serializer = DataPointSerializer(instance)
>>> out_serializer.data
ReturnDict([('label', 'testing'),
('coordinates', OrderedDict([('x', 1), ('y', 2)]))])
反序列化
>>> in_serializer = DataPointSerializer(data=data)
>>> in_serializer.is_valid()
True
>>> in_serializer.validated_data
OrderedDict([('label', 'still testing'),
('x_coordinate', 3),
('y_coordinate', 4)])
但我们还免费获得了内置验证
>>> invalid_data = {
... "label": "still testing",
... "coordinates": {
... "x": 'a',
... "y": 'b',
... }
... }
>>> invalid_serializer = DataPointSerializer(data=invalid_data)
>>> invalid_serializer.is_valid()
False
>>> invalid_serializer.errors
ReturnDict([('coordinates',
{'x': ['A valid integer is required.'],
'y': ['A valid integer is required.']})])
因此,嵌套序列化器方法是首选。当嵌套序列化器变得不可行或过于复杂时,您将使用自定义字段方法。
第三方包
以下第三方软件包也可用。
DRF 复合字段
drf-compound-fields 软件包提供“复合”序列化器字段,例如简单值的列表,这些字段可以通过其他字段来描述,而不是使用 many=True
选项的序列化器。还提供了类型化字典和值的字段,这些值可以是特定类型或该类型的项目列表。
DRF 额外字段
drf-extra-fields 软件包为 REST 框架提供了额外的序列化器字段,包括 Base64ImageField
和 PointField
类。
djangorestframework-recursive
the djangorestframework-recursive 软件包提供了一个 RecursiveField
,用于序列化和反序列化递归结构
django-rest-framework-gis
django-rest-framework-gis 软件包为 django rest 框架提供了地理附加项,例如 GeometryField
字段和 GeoJSON 序列化器。
django-rest-framework-hstore
django-rest-framework-hstore 软件包提供了一个 HStoreField
来支持 django-hstore DictionaryField
模型字段。