serializers.DecimalField(max_digits=19, decimal_places=10)
这个字段还接受一个可选参数,coerce_to_string
。如果设置为 True
,则表示将以字符串形式输出。如果设置为 False
,则表示将保留为 Decimal
实例,最终表示形式将由渲染器确定。
如果未设置,则默认设置为与 COERCE_DECIMAL_TO_STRING
setting 相同的值,除非另行设置,否则该值为 True
。
日期和时间字段
DateTimeField
表示日期和时间。
对应于 django.db.models.fields.DateTimeField
.
签名: DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
format
- 表示输出格式的字符串。如果未指定,则默认为与 DATETIME_FORMAT
settings key 相同的值,除非设置,否则将为 'iso-8601'
。设置为格式化字符串则表明 to_representation
返回值应该被强制为字符串输出。格式化字符串如下所述。将此值设置为 None
表示 Python datetime
对象应由 to_representation
返回。在这种情况下,日期时间编码将由渲染器确定。
input_formats
- 表示可用于解析日期的输入格式的字符串列表。 如果未指定,则将使用 DATETIME_INPUT_FORMATS
设置,该设置默认为 ['iso-8601']
。
DateTimeField
格式化字符串。
格式化字符串可以是明确指定的 Python strftime 格式,也可以是使用 ISO 8601 风格 datetime 的特殊字符串 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
settings key 相同的值,除非设置,否则将为 'iso-8601'
。设置为格式化字符串则表明 to_representation
返回值应该被强制为字符串输出。格式化字符串如下所述。将此值设置为 None
表示 Python date
对象应由 to_representation
返回。在这种情况下,日期时间编码将由渲染器确定。
input_formats
- 表示可用于解析日期的输入格式的字符串列表。 如果未指定,则将使用 DATE_INPUT_FORMATS
设置,该设置默认为 ['iso-8601']
。
DateField
格式化字符串
格式化字符串可以是明确指定的 Python strftime 格式,也可以是使用 ISO 8601 风格 date 的特殊字符串 iso-8601
。(例如 '2013-01-29'
)
TimeField
表示时间。
对应于 django.db.models.fields.TimeField
签名: TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
format
- 表示输出格式的字符串。如果未指定,则默认为与 TIME_FORMAT
settings key 相同的值,除非设置,否则将为 'iso-8601'
。设置为格式化字符串则表明 to_representation
返回值应该被强制为字符串输出。格式化字符串如下所述。将此值设置为 None
表示 Python time
对象应由 to_representation
返回。在这种情况下,日期时间编码将由渲染器确定。
input_formats
- 表示可用于解析日期的输入格式的字符串列表。 如果未指定,则将使用 TIME_INPUT_FORMATS
设置,该设置默认为 ['iso-8601']
。
TimeField
格式化字符串
格式化字符串可以是明确指定的 Python strftime 格式,也可以是使用 ISO 8601 风格 time 的特殊字符串 iso-8601
。(例如 '12:34:56.000000'
)
DurationField
表示持续时间。
对应于 django.db.models.fields.DurationField
这些字段的 validated_data
将包含一个 datetime.timedelta
实例。该表示形式是遵循格式 '[DD] [HH:[MM:]]ss[.uuuuuu]'
的字符串。
签名: DurationField()
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…"
Allow_blank
和 allow_null
都是 ChoiceField
上的有效选项,但强烈建议只使用一个而不是两个都用。对于文本选择,allow_blank
应该是首选,allow_null
应该是数字或其他非文本选项的首选。
文件上传字段
解析和文件上传。
FileField
和 ImageField
类只适用于 MultiPartParser
或 FileUploadParser
。大多数解析器,例如, e.g. 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
settings key 的值,除非另有设置,否则为 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
settings key 的值,除非另有设置,否则为 True
。
需要 Pillow
库或 PIL
库。 建议使用 Pillow
库。 因为 PIL
已经不再维护。
ListField
验证对象列表的字段类。
签名: ListField(child=<A_FIELD_INSTANCE>, min_length=None, max_length=None)
child
- 应该用于验证列表中的对象的字段实例。如果未提供此参数,则列表中的对象将不会被验证。
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>)
child
- 应该用于验证字典中的值的字段实例。如果未提供此参数,则映射中的值将不会被验证。
例如,要创建一个验证字符串到字符串映射的字段,可以这样写:
document = DictField(child=CharField())
复制代码
你也可以像使用 ListField
一样使用声明式风格。例如:
class DocumentField(DictField):
child = CharField()
复制代码
JSONField
验证传入的数据结构由有效 JSON 基元组成的字段类。在其二进制模式下,它将表示并验证 JSON 编码的二进制字符串。
签名: JSONField(binary)
binary
- 如果设置为 True
,那么该字段将输出并验证 JSON 编码的字符串,而不是原始数据结构。默认是 False
.
其他类型的字段
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
类,而不是将所有这些字段公开给最终用户。
ModelField
可以绑定到任意模型字段的通用字段。ModelField
类将序列化/反序列化的任务委托给其关联的模型字段。该字段可用于为自定义模型字段创建序列化字段,而无需创建新的自定义序列化字段。
ModelSerializer
使用此字段来对应自定义模型字段类。
签名: ModelField(model_field=<Django ModelField instance>)
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
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
自定义字段
如果你想创建自定义字段,则需要对 Field
进行子类化,然后重写 .to_representation()
和 .to_internal_value()
方法中的一个或两个。这两个方法用于在初始数据类型和基本序列化数据类型之间进行转换。基本数据类型通常是 number,string, boolean, date
/time
/datetime
或 None
。它们也可以是任何仅包含其他基本对象的列表或字典。其他类型可能会支持,但具体取决于你使用的渲染器。
调用 .to_representation()
方法将初始数据类型转换为基本的可序列化数据类型。
调用 to_internal_value()
方法将基本数据类型恢复为其内部 python 表示形式。如果数据无效,此方法应该引发 serializers.ValidationError
异常。
请注意,2.x 版本中存在的 WritableField
类不再存在。 应此,如果字段需要支持数据输入,则应该继承 Field
并覆盖 to_internal_value()
。
看几个栗子
基本的自定义字段
我们来看一个序列化代表 RGB 颜色值的类的例子:
class Color(object):
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, obj):
return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.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, obj):
return obj
def to_representation(self, obj):
Serialize the object's class name.
return obj.__class__.__name__
复制代码
抛出验证错误
我们上面的 ColorField
类目前不执行任何数据验证。为了表示无效数据,我们应该引发一个 serializers.ValidationError
,如下所示:
def to_internal_value(self, data):
if not isinstance(data, six.text_type):
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, six.text_type):
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, obj):
ret = {
"x": obj.x_coordinate,
"y": obj.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()
>>> 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']
复制代码
这里,我们在 IntegerField
声明中处理目标和源属性对(x
和 x_coordinate
,y
和 y_coordinate
)之间的映射。这是使用了 source ='*'
的 NestedCoordinateSerializer
。
新的 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()
>>> 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.']})])
复制代码
出于这个原因,可以首先尝试嵌套序列化类方法。当嵌套序列化类变得不可行或过于复杂时,可以使用自定义字段方法。