fields.py

序列化器字段

Form 类中的每个字段不仅负责验证数据,还负责“清理”数据,即将其规范化为一致的格式。

Django 文档

序列化字段处理在原始值和内部数据类型之间的转换。它们还处理验证输入值,以及从其父对象中检索和设置值。


注意:序列化字段在 fields.py 中声明,但按照惯例,你应该使用 from rest_framework import serializers 导入它们,并将字段称为 serializers.<FieldName>


核心参数

每个序列化字段类构造函数至少接受这些参数。一些字段类接受其他字段特定的参数,但以下参数始终应被接受

read_only

只读字段包含在 API 输出中,但不应该包含在创建或更新操作期间的输入中。任何错误包含在序列化器输入中的“只读”字段都将被忽略。

将其设置为 True 以确保在序列化表示形式时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。

默认为 False

write_only

将其设置为 True 以确保在更新或创建实例时可以使用该字段,但在序列化表示形式时不包含该字段。

默认为 False

required

通常,如果反序列化期间未提供字段,则会引发错误。如果反序列化期间不需要此字段,则设置为 false。

将此项设为 False 还允许在序列化实例时省略对象属性或字典键。如果键不存在,它将不会包含在输出表示中。

默认为 True。如果您正在使用 模型序列化器,如果您在 Model 中的字段中指定了 blank=Truedefaultnull=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 值意味着该字段不是必需的。同时包含 defaultrequired 关键字参数是无效的,并且会引发错误。

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_relatedselect_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.CharFielddjango.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=Trueallow_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.IPAddressFielddjango.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.IntegerFielddjango.db.models.fields.SmallIntegerFielddjango.db.models.fields.PositiveIntegerFielddjango.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 应返回 Python datetime 对象。在这种情况下,日期时间编码将由渲染器确定。
  • input_formats - 表示可用于解析日期的输入格式的字符串列表。如果未指定,将使用 DATETIME_INPUT_FORMATS 设置,其默认为 ['iso-8601']
  • default_timezone - 表示时区的 tzinfo 子类(zoneinfopytz)。如果未指定且启用了 USE_TZ 设置,这将默认为 当前时区。如果禁用了 USE_TZ,则日期时间对象将是朴素的。

DateTimeField 格式字符串。

格式字符串可以是明确指定格式的 Python strftime 格式,也可以是特殊字符串 'iso-8601',表示应使用 ISO 8601 样式的日期时间。(例如 '2013-01-29T12:34:56.000000Z'

当格式的 None 值用于 datetime 对象时,将由 to_representation 返回,最终输出表示形式将由渲染器类确定。

auto_nowauto_now_add 模型字段。

使用 ModelSerializerHyperlinkedModelSerializer 时,请注意任何具有 auto_now=Trueauto_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 表示 Python date 对象应由 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 表示 Python time 对象应由 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_blankallow_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_blankallow_null 选项都是有效的,但强烈建议只使用一个,而不是同时使用。对于文本选择,应首选 allow_blank,对于数字或其他非文本选择,应首选 allow_null


文件上传字段

解析器和文件上传。

FileFieldImageField 类仅适用于 MultiPartParserFileUploadParser。大多数解析器(例如 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_expiredAccount 模型上的一个属性,那么以下序列化器将自动将其生成为 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/datetimeNone。它们还可以是任何列表或字典之类的对象,其中仅包含其他原始对象。根据您使用的渲染器,还可能支持其他类型。

调用 .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_coordinatey_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']

此处,目标和源属性对(xx_coordinateyy_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 框架提供了额外的序列化器字段,包括 Base64ImageFieldPointField 类。

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 模型字段。