Official original text link this series of articles github address reprint please indicate the source
The Serializer field
Each field in the Form class is responsible not only for validating the data, but also for “cleaning” it — normalizing it into a consistent format.
– the Django documentation
Serialization fields handle conversions between base data types and other data types, such as custom classes. They can also validate data and retrieve and set values from their parent objects.
Note: Serialized fields are declared in files.py, but by convention you should use from rest_framework import serializers and reference them as serializers.
.
Core parameter
The constructor of each serialized field class requires some parameters. Some field classes require additional parameters specific to that field, but the following parameters should always be accepted:
read_only
Read-only fields are included in the output API and should not be included in the input API where a create or update operation is required. Incorrect inclusion of ‘read_only’ in serialized class input is ignored.
Setting it to True ensures that the field is used when serializing representations, but not when creating or updating instances during deserialization.
The default is False
write_only
Set it to True to ensure that the field can be used when updating or creating instances, but not included when serializing representations.
The default is False
required
If the supplied field is not present during deserialization, an error usually occurs. If this field is not needed during deserialization, it should be set to false.
Setting this to False also allows object attributes or dictionary keys to be omitted from the output when serializing the instance. If the key does not exist, it will not be included in the output representation.
The default is True
allow_null
If None is passed to the serialized field, an error is usually raised. Set this keyword argument to True if None should be considered valid.
Note that setting this parameter to True will mean that the default value of the serialization output is NULL, but it does not mean that the default value of the input deserialization is.
The default is False
default
If set, the default value is given and will be used when no input value is provided. If not set, the default behavior is not to populate the property.
Partial update operations should not use default. In some cases, only the fields provided in the incoming data will return the validation value.
It can be set to a function or other callable object, in which case it will be called every time the value is used. When called, it will not receive any arguments. If the callable has the set_context method, it is called every time a field instance is fetched as a parameter. This works in the same way as the validator.
When serializing an instance, the default value is used if the object attribute or dictionary key does not exist in the instance.
Note that setting the default value means that this field is not required. Keyword arguments that include both default and required are invalid and raise an error.
source
The name of the property that will be used to populate the field. It can be a method that accepts only self, such as URLField(source=’ get_absolute_URL ‘), or a dot notation to iterate over properties, such as EmailField(source=’user.email’). When using dot notation, you may need to provide a default value if any object does not exist or is empty during the property traversal.
Source =’*’ has the special meaning to indicate that the entire object should be passed to this field. This is useful for creating nested representations or for fields that need access to the full object to determine the output representation.
The default is the name of the field.
validators
The list of validation functions that should be applied to the incoming field input should throw a validation error or return only. Validator function normally should trigger serializers ValidationError, but also support and Django’s built-in ValidationError Django code base or third-party Django package defined in the validator compatible.
error_messages
A dictionary where key is the error code and value is the corresponding error message.
label
A short text string that can be used as the name of an HTML form field or other descriptive element.
help_text
A text string that can be used to describe a field in an HTML form field or other descriptive element.
initial
Should be used to prepopulate the values of HTML form fields. You might pass a callable object, just like you would with any regular Django Field:
import datetime
from rest_framework import serializers
class ExampleSerializer(serializers.Serializer):
day = serializers.DateField(initial=datetime.date.today)
Copy the code
style
A dictionary that can be used to control the key-value pairs of renderer fields.
Here are two examples of ‘input_type’ and ‘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'})Copy the code
Boolean fields
BooleanField
Represents a Boolean value.
When encoding forms with HTML, note that omitting a Boolean value is considered to set the field to False, even if it specifies the default=True option. This is because the HTML check box represents the unchecked state by omitting the value, so the REST framework treats the omission as an empty check box.
Note that the default BooleanField instance will be generated using the required=False option (because Django models.BooleanField is always blank=True). If you want to change this behavior, declare the BooleanField explicitly on the serialized class.
Corresponding with the django. Db. Models. Fields. BooleanField.
Signature: BooleanField ()
NullBooleanField
Represents a Boolean value that also accepts None as a valid value.
Corresponding with the django. Db. Models. Fields. NullBooleanField.
Signature: NullBooleanField ()
String field
CharField
Represents text. You can use max_length, min_length to validate (or limit) the length of text.
Corresponding with django. Db. Models. Fields. CharField or django. Db. Models. Fields. The TextField.
CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
max_length
– Verify that the input contains no more than this number of characters.min_length
– Verify that the input contains at least this number of characters.allow_blank
– If set toTrue
, the empty string should be considered a valid value. If set toFalse
, the empty string is considered invalid and raises a validation error. The default isFalse
.trim_whitespace
– If set toTrue
Before and after whitespace will be deleted. The default isTrue
.
The allow_null option is also available for string fields, although it is not recommended over allow_blank. Setting both allow_blank=True and allow_null=True is valid, but doing so means that string representations allow two different types of null values, which can lead to data inconsistencies and subtle application errors.
EmailField
Represents text that validates as a valid E-mail address.
Corresponding with the django. Db. Models. Fields. EmailField
EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField
Represents text that verifies that a given value matches a regular expression.
Corresponding with the django. Forms. Fields. RegexField.
RegexField(regex, max_length=None, min_length=None, allow_blank=False)
The mandatory regex argument can be either a string or a compiled Python regular expression object.
Using the Django Django. Core. The validators. RegexValidator for validation.
SlugField
A RegexField that validates the input against the mode [A-zA-Z0-9_ -]+.
Corresponding with the django. Db. Models. Fields. SlugField.
SlugField(max_length=50, min_length=None, allow_blank=False)
URLField
A RegexField that validates the input against the URL matching pattern. The fully qualified URL format is http://
/
Corresponding with the django. Db. Models. Fields. URLField. Using the Django Django. Core. The validators. URLValidator for validation.
URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField
Make sure the field entered is a valid UUID string. The to_internal_value method returns a UUID.uuid instance. On output, the field returns a string in the canonical hyphenated format, for example:
"de305d54-75b4-431b-adb2-eb6b9e546013"
Copy the code
Signature: UUIDField (format = ‘hex_verbose’)
format
: Determines the representation of the UUID value'hex_verbose'
– Authoritative hexadecimal representation, including a hyphen:"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
'hex'
– Compact hexadecimal representation without a hyphen:"5ce0e9a55ffa654bcee01238041fb31a"
'int'
-128-bit integer:"123456789012312313134124512351145145114"
'urn'
-RFC 4122 URN"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
Modify theformat
Only the presentation value is affected. All formats have beento_internal_value
Accept it.
FilePathField
A field whose options are limited to file names in a directory on the file system.
Corresponding to the django. Forms. Fields. FilePathField.
Signature: FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)
path
– FilePathField Specifies the absolute file system path of the directory from which to select.match
– A string regular expression used to filter filenames.recursive
– Specifies whether all subdirectories of a path should be included. The default value isFalse
.allow_files
– Whether files at the specified location should be included. The default value isTrue
. This parameter orallow_folders
It must beTrue
. One of the two attributes must betrue
)allow_folders
– Whether the folder at the specified location should be included. The default value isFalse
. This parameter orallow_files
It must beTrue
. One of the two attributes must betrue
)
IPAddressField
Make sure the input is a valid IPv4 or IPv6 string.
Corresponding to django. Forms. Fields. IPAddressField and django forms. Fields. GenericIPAddressField.
IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
protocol
Limits the valid input to the specified protocol. The accepted value is'both'
(Default),'IPv4'
或'IPv6'
. Matching is case insensitive.unpack_ipv4
Decompress the IPv4 mapping address, as shown in: : FFFF: 192.0.2.1
. If this option is enabled, the address will be unpacked to 192.0.2.1. It is disabled by default. Only in theprotocol
Set to'both'
When use.
The digital field
IntegerField
Represents an integer.
Corresponding to the django. Db. Models. Fields. IntegerField, django. Db. Models. Fields. SmallIntegerField, Django. Db. Models. Fields. PositiveIntegerField and django db. Models. Fields. PositiveSmallIntegerField.
IntegerField(max_value=None, min_value=None)
max_value
Verify that the supplied number is not greater than this value.min_value
Verify that the supplied number is not less than this value.
FloatField
Represents a floating point.
Corresponding to the django. Db. Models. Fields. FloatField.
Signature: FloatField(max_value=None, min_value=None)
max_value
Verify that the supplied number is not greater than this value.min_value
Verify that the supplied number is not less than this value.
DecimalField
Represents Decimal, represented by Python as an instance of Decimal.
Corresponding to the django. Db. Models. Fields. DecimalField.
Coerce_to_string =None, max_value=None, min_value=None)
max_digits
Maximum number of digits allowed. It must beNone
Or greater than or equal todecimal_places
The integer.decimal_places
Number of decimal places.coerce_to_string
Set to if a string value should be returnedTrue
; If should returnDecimal
Object is set toFalse
. The default value andCOERCE_DECIMAL_TO_STRING
The Settings key has the same value, which will be, unless overriddenTrue
. If the serialized object returnsDecimal
Object, the final output format is determined by the renderer. Note the Settingslocalize
Will force the value to beTrue
.max_value
Verify that the supplied number is not greater than this value.min_value
Verify that the supplied number is not less than this value.localize
Set toTrue
To enable input and output localization based on the current locale. It also forcescoerce_to_string
为True
. The default isFalse
. Notice if you set it in the Settings fileUSE_L10N=True
, data formatting is enabled.rounding
Sets the rounding mode to use when quantizing to configuration accuracy. Valid values aredecimal
Module rounding mode. The default isNone
.
Usage examples
To verify numbers up to 999 to 2 decimal places, use:
serializers.DecimalField(max_digits=5, decimal_places=2)
Copy the code
Use 10 decimal places to verify that the number does not exceed 1 billion:
serializers.DecimalField(max_digits=19, decimal_places=10)
Copy the code
This field also accepts an optional parameter, COERce_TO_STRING. If set to True, it will be printed as a string. If set to False, it means that the Decimal instance is retained and the final representation is determined by the renderer.
If not set, it defaults to the same value as COERCE_DECIMAL_TO_STRING setting, which is True unless otherwise set.
Date and time fields
DateTimeField
Represents the date and time.
Corresponding to the django. Db. Models. Fields. DateTimeField.
Signature: DateTimeField(format= API_settings. DATETIME_FORMAT, input_formats=None)
format
– A string representing the output format. If this parameter is not specified, the default value is andDATETIME_FORMAT
Same value for Settings key, unless set'iso-8601'
. If set to a formatted stringto_representation
The return value should be forced as string output. The formatting string is described below. Set this value toNone
Said the Pythondatetime
Object should beto_representation
To return. In this case, the date and time encoding is determined by the renderer.input_formats
– Represents a list of strings representing input formats that can be used to parse dates. If not specified, it will be usedDATETIME_INPUT_FORMATS
Setting, which defaults to['iso-8601']
.
DateTimeField
Format a string.
The format string can be an explicitly specified Python Strftime format, or a special string ISO-8601 that uses ISO 8601-style datetime. (example: ‘2013-01-29T12:34:56.000000z’)
When a Value of None is used to format a Datetime object, to_representation is returned, and the final output representation is determined by the renderer class.
auto_now
和 auto_now_add
Model field.
When using ModelSerializer or HyperlinkedModelSerializer, please note that auto_now = True or auto_now_add = True model field by default will use read_only = True.
If you want to override this behavior, you need to explicitly declare the DateTimeField in the serialized class. Such as:
class CommentSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField()
class Meta:
model = Comment
Copy the code
DateField
Represents the date.
Corresponding to the django. Db. Models. Fields. DateField
Signature: DateField(format= API_settings. DATE_FORMAT, input_formats=None)
format
– A string representing the output format. If this parameter is not specified, the default value is andDATE_FORMAT
Same value for Settings key, unless set'iso-8601'
. If set to a formatted stringto_representation
The return value should be forced as string output. The formatting string is described below. Set this value toNone
Said the Pythondate
Object should beto_representation
To return. In this case, the date and time encoding is determined by the renderer.input_formats
– Represents a list of strings representing input formats that can be used to parse dates. If not specified, it will be usedDATE_INPUT_FORMATS
Setting, which defaults to['iso-8601']
.
DateField
Formatted string
The format string can be an explicitly specified Python strftime format, or a special string ISO-8601 using ISO 8601-style Date. (e.g. ‘2013-01-29’)
TimeField
Represents time.
Corresponding to the django. Db. Models. Fields. TimeField
Signature: TimeField(format= API_settings. TIME_FORMAT, input_formats=None)
format
– A string representing the output format. If this parameter is not specified, the default value is andTIME_FORMAT
Same value for Settings key, unless set'iso-8601'
. If set to a formatted stringto_representation
The return value should be forced as string output. The formatting string is described below. Set this value toNone
Said the Pythontime
Object should beto_representation
To return. In this case, the date and time encoding is determined by the renderer.input_formats
– Represents a list of strings representing input formats that can be used to parse dates. If not specified, it will be usedTIME_INPUT_FORMATS
Setting, which defaults to['iso-8601']
.
TimeField
Formatted string
The format string can be an explicitly specified Python strftime format, or a special string ISO-8601 that uses ISO 8601-style time. (e.g. ’12:34:56.000000′)
DurationField
Indicates the duration. Corresponding to the django. Db. Models. Fields. DurationField
Validated_data for these fields will contain an instance of datetime.timedelta. The representation is a string following the format ‘[DD] [HH:[MM:]]ss[.uuuuuu]’.
Signature: DurationField ()
Select field
ChoiceField
A field that accepts values from a limited selection.
If the corresponding model field contains Choices =… “Is automatically generated by ModelSerializer.
Signature: ChoiceField (choices)
choices
– Valid value list, or(key, display_name)
List of tuples.allow_blank
– If set toTrue
, the empty string should be considered a valid value. If set toFalse
, the empty string is considered invalid and raises a validation error. The default isFalse
.html_cutoff
– If set, this will be the maximum number of options displayed in the HTML selection drop-down menu. Can be used to ensure automatic generation with a very large selection of Choicefields without blocking the rendering of templates. The default isNone
.html_cutoff_text
– Specifies a text indicator to display when a list is truncated, such as when the maximum number of items has been truncated in an HTML selection drop-down menu. It will be displayed by default"Wining {count} items..."
Allow_blank and allow_null are both valid options on ChoiceField, but it is strongly recommended to use only one rather than both. For text selections, allow_blank should be preferred, and allow_null should be preferred for numbers or other non-text options.
MultipleChoiceField
Fields that can accept a set of zero, one, or more values to choose from a limited set of choices. Take a mandatory parameter. To_internal_value returns a set containing the selected value.
Signature: MultipleChoiceField (choices)
choices
– Valid value list, or(key, display_name)
List of tuples.allow_blank
– If set toTrue
, the empty string should be considered a valid value. If set toFalse
, the empty string is considered invalid and raises a validation error. The default isFalse
.html_cutoff
– If set, this will be the maximum number of options displayed in the HTML selection drop-down menu. Can be used to ensure automatic generation with a very large selection of Choicefields without blocking the rendering of templates. The default isNone
.html_cutoff_text
– Specifies a text indicator to display when a list is truncated, such as when the maximum number of items has been truncated in an HTML selection drop-down menu. It will be displayed by default"Wining {count} items..."
Allow_blank and allow_null are both valid options on ChoiceField, but it is strongly recommended to use only one rather than both. For text selections, allow_blank should be preferred, and allow_null should be preferred for numbers or other non-text options.
File upload field
Parse and upload files.
The FileField and ImageField classes only work with MultiPartParser or FileUploadParser. Most parsers, such as e.g. JSON, do not support file uploads. Djangos regular FILE_UPLOAD_HANDLERS are used to handle uploaded files.
FileField
Represents a file. Performs Djangos standard FileField validation.
Corresponding to the django. Forms. Fields. FileField.
FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
max_length
– Specifies the maximum length of the file name.allow_empty_file
– Specifies whether empty files are allowed.use_url
– If set toTrue
, the URL string value will be used for the output representation. If set toFalse
, the filename string value will be used for the output representation. The default isUPLOADED_FILES_USE_URL
The value of Settings key, unless otherwise setTrue
.
ImageField
Represents a picture. Verify that the uploaded file content matches the known image format.
Corresponding to django. Forms. Fields. ImageField.
Signature: ImageField(max_length=None, allow_empty_file=False, use_URL =UPLOADED_FILES_USE_URL)
max_length
– Specifies the maximum length of the file name.allow_empty_file
– Specifies whether empty files are allowed.use_url
– If set toTrue
, the URL string value will be used for the output representation. If set toFalse
, the filename string value will be used for the output representation. The default isUPLOADED_FILES_USE_URL
The value of Settings key, unless otherwise setTrue
.
Pillow library or PIL library is required. The Pillow library is recommended. Because PIL is no longer maintained.
Composite field
ListField
Validates the field class of the object list.
ListField(child=
, min_length=None, max_length=None)
child
– Field instances that should be used to validate objects in the list. If this parameter is not provided, objects in the list will not be validated.min_length
– Verify that the list contains at least this number of elements.max_length
– Verify that the list contains no more than this number of elements.
For example, to validate a list of integers:
scores = serializers.ListField(
child=serializers.IntegerField(min_value=0, max_value=100))Copy the code
The ListField class also supports a declarative style, allowing you to write reusable ListField classes.
class StringListField(serializers.ListField):
child = serializers.CharField()
Copy the code
We can now reuse our custom StringListField class in our application without providing it with the Child argument.
DictField
Validates the field class of the object dictionary. Keys in the DictField are always assumed to be string values.
Signature: DictField (child = < A_FIELD_INSTANCE >)
child
– Field instance that should be used to validate values in the dictionary. If this parameter is not provided, the value in the map will not be validated.
For example, to create a field that validates a string-to-string mapping, write:
document = DictField(child=CharField())
Copy the code
You can also use the declarative style as you would with ListField. Such as:
class DocumentField(DictField):
child = CharField()
Copy the code
JSONField
Validates the field class that the incoming data structure consists of valid JSON primitives. In its binary mode, it represents and validates a JSON-encoded binary string.
Signature: JSONField (binary)
binary
– If set toTrue
, the field will output and validate the JSON-encoded string instead of the original data structure. The default isFalse
.
Other types of fields
ReadOnlyField
A field class that simply returns the value of a field without modification.
This field is used with ModelSerializer by default when it contains field names associated with attributes rather than model fields.
Signature: ReadOnlyField ()
For example, if has_expired is an attribute in the Account model, the following serializer will automatically generate ReadOnlyField:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id'.'account_name'.'has_expired')
Copy the code
HiddenField
Field classes that do not get values based on user input, but instead get values from default or callable values.
Signature: HiddenField ()
For example, to include a field that always provides the current time as part of the serialized class validation data, you could use the following:
modified = serializers.HiddenField(default=timezone.now)
Copy the code
If you need to run some validation based on some pre-provided field value, you usually only need the HiddenField class, rather than exposing all of these fields to the end user.
ModelField
Generic fields that can be bound to any model field. The ModelField class delegates serialization/deserialization to its associated model fields. This field can be used to create a serialization field for a custom model field without creating a new custom serialization field.
ModelSerializer uses this field to correspond to custom model field classes.
Signature: ModelField(model_field=
)
The ModelField class is typically used for internal use, but can be used by the API if desired. In order to instantiate the ModelField correctly, you must pass a field attached to the instantiated model. For example: ModelField (model_field = MyModel (.) _meta. Get_field (‘ custom_field ‘))
SerializerMethodField
This is a read-only field. It gets its value by calling the method of the serialized class to which it connects. It can be used to add any type of data to the serialized representation of an object.
Signature: SerializerMethodField (method_name = None)
method_name
– The name of the method to call the serialized object. If it is not included, the default value isget_<field_name>
.
The serialization method referenced by the method_name parameter should take one argument (except self), which is the object to serialize. It should return whatever you want to include in the serialized representation of the object. Such as:
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
Copy the code
Custom field
If you want to create custom fields, you’ll need to subclass Field and override one or both of the.to_representation() and.to_internal_value() methods. These two methods are used to convert between the initial data type and the base serialized data type. The basic data types are usually number, String, Boolean, date/time/datetime or None. They can also be any list or dictionary that contains only other basic objects. Other types may be supported, depending on the renderer you’re using.
The.to_representation() method is called to convert the initial data type to the base serializable data type.
Call the to_internal_value() method to restore the base data type to its internal Python representation. If the data is invalid, this method should lead to serializers. Abnormal ValidationError.
Note that the WritableField class that existed in version 2.x no longer exists. As such, if the Field needs to support data entry, it should inherit Field and override to_internal_value().
Look at some chestnuts
Basic custom fields
Let’s look at an example of serializing a class that represents an RGB color value:
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)
Copy the code
By default, field values are treated as properties mapped to objects. If you want to customize how field values are accessed, you need to override.get_attribute() and/or.get_value().
Let’s create a field that can be used to represent the class name of the serialized object:
class ClassNameField(serializers.Field):
def get_attribute(self, obj):
# We pass the object instance onto `to_representation`,
# not just the field attribute.
return obj
def to_representation(self, obj):
""" Serialize the object's class name. """
return obj.__class__.__name__
Copy the code
Throw a validation error
Our ColorField class above does not currently perform any data validation. To show the invalid data, we should trigger a serializers ValidationError, as shown below:
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)
Copy the code
The.fail() method is a shortcut to raise ValidationError, which receives the message string from the error_messages dictionary. Such as:
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)
Copy the code
This style makes your error messages clear and separate from the code, and should be preferred.
usesource='*'
Here we will give an example of a flat DataPoint model with x_coordinate and y_coordinate properties.
class DataPoint(models.Model):
label = models.CharField(max_length=50)
x_coordinate = models.SmallIntegerField()
y_coordinate = models.SmallIntegerField()
Copy the code
Using custom fields and source =’*’, we can provide nested representations of coordinate pairs:
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=The '*')
class Meta:
model = DataPoint
fields = ['label'.'coordinates']
Copy the code
Note that this example does not handle validation. Nested serialized classes that use source =’*’ handle coordinate nesting better, with two instances of IntegerField, each with its own source pointing to the related field.
However, the key point of this example is:
to_representation
Pass the entireDataPoint
Object and is mapped to the desired output.
>>> 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})])
Copy the code
- Unless our field is read-only, otherwise
to_internal_value
You must map back to a dictionary suitable for updating the target object. usesource='*'
,to_internal_value
Will update the data dictionary for root validation, not the individual keys.
>>> 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)])
Copy the code
For completeness, we do the same thing again, but with the nested serialization method suggested above:
class NestedCoordinateSerializer(serializers.Serializer):
x = serializers.IntegerField(source='x_coordinate')
y = serializers.IntegerField(source='y_coordinate')
class DataPointSerializer(serializers.ModelSerializer):
coordinates = NestedCoordinateSerializer(source=The '*')
class Meta:
model = DataPoint
fields = ['label'.'coordinates']
Copy the code
Here, we deal with mappings between target and source attribute pairs (X and X_coordinate, y and y_coordinate) in the IntegerField declaration. This is the use of the source = ‘*’ NestedCoordinateSerializer.
The new DataPointSerializer shows the same behavior as the custom field method.
Serialization:
>>> out_serializer = DataPointSerializer(instance)
>>> out_serializer.data
ReturnDict([('label'.'testing'),
('coordinates', OrderedDict([('x'.1), ('y'.2))))Copy the code
Deserialization:
>>> in_serializer = DataPointSerializer(data=data)
>>> in_serializer.is_valid()
True
>>> in_serializer.validated_data
OrderedDict([('label'.'still testing'),
('x_coordinate'.3),
('y_coordinate'.4)])
Copy the code
Although no validation is written, built-in validation can be used:
>>> 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.']})])
Copy the code
For this reason, you can first try nesting serialized class methods. Custom field methods can be used when nesting serialized classes becomes impractical or too complex.