class Serializer
from rest_framework.serializers import Serializer
Ancestors (MRO)
- Serializer
- BaseSerializer
- Field
Descendants
Attributes
Defined in | |
---|---|
_creation_counter = 3
|
Field |
_declared_fields = OrderedDict()
|
Serializer |
_readable_fields = <django.utils.functional.cached_property object at 0x7f385d6e0220>
|
Serializer |
_writable_fields = <django.utils.functional.cached_property object at 0x7f385d6e01c0>
|
Serializer |
context = <property object at 0x7f385d864cc0>
|
Field |
data = <property object at 0x7f385d6d7360>
|
Serializer |
data = <property object at 0x7f385dd6bae0>
|
BaseSerializer |
default_empty_html = <class 'rest_framework.fields.empty'>
|
Field |
default_error_messages = {'invalid': 'Invalid data. Expected a dictionary, but got {datatype}.'}
|
Serializer |
default_error_messages = {'required': 'This field is required.', 'null': 'This field may not be null.'}
|
Field |
default_validators = []
|
Field |
errors = <property object at 0x7f385d6e2040>
|
Serializer |
errors = <property object at 0x7f385da7abd0>
|
BaseSerializer |
fields = <property object at 0x7f385d6d3e50>
|
Serializer |
initial = None
|
Field |
root = <property object at 0x7f385d864c20>
|
Field |
validated_data = <property object at 0x7f385d6d3310>
|
BaseSerializer |
validators = <property object at 0x7f385d864c70>
|
Field |
Methods used but not implemented in this class
- default
Methods
def
_read_only_defaults(self):
¶
Serializer
def _read_only_defaults(self):
fields = [
field for field in self.fields.values()
if (field.read_only) and (field.default != empty) and (field.source != '*') and ('.' not in field.source)
]
defaults = OrderedDict()
for field in fields:
try:
default = field.get_default()
except SkipField:
continue
defaults[field.field_name] = default
return defaults
def
bind(self, field_name, parent):
¶
Field
Initializes the field name and parent for the field instance. Called when a field is added to the parent serializer instance.
def bind(self, field_name, parent):
"""
Initializes the field name and parent for the field instance.
Called when a field is added to the parent serializer instance.
"""
# In order to enforce a consistent style, we error if a redundant
# 'source' argument has been used. For example:
# my_field = serializer.CharField(source='my_field')
assert self.source != field_name, (
"It is redundant to specify `source='%s'` on field '%s' in "
"serializer '%s', because it is the same as the field name. "
"Remove the `source` keyword argument." %
(field_name, self.__class__.__name__, parent.__class__.__name__)
)
self.field_name = field_name
self.parent = parent
# `self.label` should default to being based on the field name.
if self.label is None:
self.label = field_name.replace('_', ' ').capitalize()
# self.source should default to being the same as the field name.
if self.source is None:
self.source = field_name
# self.source_attrs is a list of attributes that need to be looked up
# when serializing the instance, or populating the validated data.
if self.source == '*':
self.source_attrs = []
else:
self.source_attrs = self.source.split('.')
def
create(self, validated_data):
¶
BaseSerializer
def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')
def
fail(self, key, **kwargs):
¶
Field
A helper method that simply raises a validation error.
def fail(self, key, **kwargs):
"""
A helper method that simply raises a validation error.
"""
try:
msg = self.error_messages[key]
except KeyError:
class_name = self.__class__.__name__
msg = MISSING_ERROR_MESSAGE.format(class_name=class_name, key=key)
raise AssertionError(msg)
message_string = msg.format(**kwargs)
raise ValidationError(message_string, code=key)
def
get_attribute(self, instance):
¶
Field
Given the *outgoing* object instance, return the primitive value that should be used for this field.
def get_attribute(self, instance):
"""
Given the *outgoing* object instance, return the primitive value
that should be used for this field.
"""
try:
return get_attribute(instance, self.source_attrs)
except (KeyError, AttributeError) as exc:
if self.default is not empty:
return self.get_default()
if self.allow_null:
return None
if not self.required:
raise SkipField()
msg = (
'Got {exc_type} when attempting to get a value for field '
'`{field}` on serializer `{serializer}`.\nThe serializer '
'field might be named incorrectly and not match '
'any attribute or key on the `{instance}` instance.\n'
'Original exception text was: {exc}.'.format(
exc_type=type(exc).__name__,
field=self.field_name,
serializer=self.parent.__class__.__name__,
instance=instance.__class__.__name__,
exc=exc
)
)
raise type(exc)(msg)
def
get_default(self):
¶
Field
Return the default value to use when validating data if no input is provided for this field. If a default has not been set for this field then this will simply raise `SkipField`, indicating that no value should be set in the validated data for this field.
def get_default(self):
"""
Return the default value to use when validating data if no input
is provided for this field.
If a default has not been set for this field then this will simply
raise `SkipField`, indicating that no value should be set in the
validated data for this field.
"""
if self.default is empty or getattr(self.root, 'partial', False):
# No default, or this is a partial update.
raise SkipField()
if callable(self.default):
if hasattr(self.default, 'set_context'):
self.default.set_context(self)
return self.default()
return self.default
def
get_fields(self):
¶
Serializer
Returns a dictionary of {field_name: field_instance}.
def get_fields(self):
"""
Returns a dictionary of {field_name: field_instance}.
"""
# Every new serializer is created with a clone of the field instances.
# This allows users to dynamically modify the fields on a serializer
# instance without affecting every other serializer instance.
return copy.deepcopy(self._declared_fields)
def
get_initial(self):
¶
Serializer
def get_initial(self):
if hasattr(self, 'initial_data'):
# initial_data may not be a valid type
if not isinstance(self.initial_data, Mapping):
return OrderedDict()
return OrderedDict([
(field_name, field.get_value(self.initial_data))
for field_name, field in self.fields.items()
if (field.get_value(self.initial_data) is not empty) and
not field.read_only
])
return OrderedDict([
(field.field_name, field.get_initial())
for field in self.fields.values()
if not field.read_only
])
Field
Return a value to use when the field is being returned as a primitive value, without any object instance.
def get_initial(self):
"""
Return a value to use when the field is being returned as a primitive
value, without any object instance.
"""
if callable(self.initial):
return self.initial()
return self.initial
def
get_validators(self):
¶
Serializer
Returns a list of validator callables.
def get_validators(self):
"""
Returns a list of validator callables.
"""
# Used by the lazily-evaluated `validators` property.
meta = getattr(self, 'Meta', None)
validators = getattr(meta, 'validators', None)
return validators[:] if validators else []
Field
def get_validators(self):
return self.default_validators[:]
def
get_value(self, dictionary):
¶
Serializer
def get_value(self, dictionary):
# We override the default field access in order to support
# nested HTML forms.
if html.is_html_input(dictionary):
return html.parse_html_dict(dictionary, prefix=self.field_name) or empty
return dictionary.get(self.field_name, empty)
Field
Given the *incoming* primitive data, return the value for this field that should be validated and transformed to a native value.
def get_value(self, dictionary):
"""
Given the *incoming* primitive data, return the value for this field
that should be validated and transformed to a native value.
"""
if html.is_html_input(dictionary):
# HTML forms will represent empty fields as '', and cannot
# represent None or False values directly.
if self.field_name not in dictionary:
if getattr(self.root, 'partial', False):
return empty
return self.default_empty_html
ret = dictionary[self.field_name]
if ret == '' and self.allow_null:
# If the field is blank, and null is a valid value then
# determine if we should use null instead.
return '' if getattr(self, 'allow_blank', False) else None
elif ret == '' and not self.required:
# If the field is blank, and emptiness is valid then
# determine if we should use emptiness instead.
return '' if getattr(self, 'allow_blank', False) else empty
return ret
return dictionary.get(self.field_name, empty)
def
is_valid(self, raise_exception=False):
¶
BaseSerializer
def is_valid(self, raise_exception=False):
assert not hasattr(self, 'restore_object'), (
'Serializer `%s.%s` has old-style version 2 `.restore_object()` '
'that is no longer compatible with REST framework 3. '
'Use the new-style `.create()` and `.update()` methods instead.' %
(self.__class__.__module__, self.__class__.__name__)
)
assert hasattr(self, 'initial_data'), (
'Cannot call `.is_valid()` as no `data=` keyword argument was '
'passed when instantiating the serializer instance.'
)
if not hasattr(self, '_validated_data'):
try:
self._validated_data = self.run_validation(self.initial_data)
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {}
if self._errors and raise_exception:
raise ValidationError(self.errors)
return not bool(self._errors)
def
many_init(cls, *args, **kwargs):
¶
BaseSerializer
This method implements the creation of a `ListSerializer` parent class when `many=True` is used. You can customize it if you need to control which keyword arguments are passed to the parent, and which are passed to the child. Note that we're over-cautious in passing most arguments to both parent and child classes in order to try to cover the general case. If you're overriding this method you'll probably want something much simpler, eg: @classmethod def many_init(cls, *args, **kwargs): kwargs['child'] = cls() return CustomListSerializer(*args, **kwargs)
@classmethod
def many_init(cls, *args, **kwargs):
"""
This method implements the creation of a `ListSerializer` parent
class when `many=True` is used. You can customize it if you need to
control which keyword arguments are passed to the parent, and
which are passed to the child.
Note that we're over-cautious in passing most arguments to both parent
and child classes in order to try to cover the general case. If you're
overriding this method you'll probably want something much simpler, eg:
@classmethod
def many_init(cls, *args, **kwargs):
kwargs['child'] = cls()
return CustomListSerializer(*args, **kwargs)
"""
allow_empty = kwargs.pop('allow_empty', None)
child_serializer = cls(*args, **kwargs)
list_kwargs = {
'child': child_serializer,
}
if allow_empty is not None:
list_kwargs['allow_empty'] = allow_empty
list_kwargs.update({
key: value for key, value in kwargs.items()
if key in LIST_SERIALIZER_KWARGS
})
meta = getattr(cls, 'Meta', None)
list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
return list_serializer_class(*args, **list_kwargs)
def
run_validation(self, data= ):
¶
Serializer
We override the default `run_validation`, because the validation performed by validators and the `.validate()` method should be coerced into an error dictionary with a 'non_fields_error' key.
def run_validation(self, data=empty):
"""
We override the default `run_validation`, because the validation
performed by validators and the `.validate()` method should
be coerced into an error dictionary with a 'non_fields_error' key.
"""
(is_empty_value, data) = self.validate_empty_values(data)
if is_empty_value:
return data
value = self.to_internal_value(data)
try:
self.run_validators(value)
value = self.validate(value)
assert value is not None, '.validate() should return the validated data'
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
return value
Field
Validate a simple representation and return the internal value. The provided data may be `empty` if no representation was included in the input. May raise `SkipField` if the field should not be included in the validated data.
def run_validation(self, data=empty):
"""
Validate a simple representation and return the internal value.
The provided data may be `empty` if no representation was included
in the input.
May raise `SkipField` if the field should not be included in the
validated data.
"""
(is_empty_value, data) = self.validate_empty_values(data)
if is_empty_value:
return data
value = self.to_internal_value(data)
self.run_validators(value)
return value
def
run_validators(self, value):
¶
Serializer
Add read_only fields with defaults to value before running validators.
def run_validators(self, value):
"""
Add read_only fields with defaults to value before running validators.
"""
to_validate = self._read_only_defaults()
to_validate.update(value)
super(Serializer, self).run_validators(to_validate)
Field
Test the given value against all the validators on the field, and either raise a `ValidationError` or simply return.
def run_validators(self, value):
"""
Test the given value against all the validators on the field,
and either raise a `ValidationError` or simply return.
"""
errors = []
for validator in self.validators:
if hasattr(validator, 'set_context'):
validator.set_context(self)
try:
validator(value)
except ValidationError as exc:
# If the validation error contains a mapping of fields to
# errors then simply raise it immediately rather than
# attempting to accumulate a list of errors.
if isinstance(exc.detail, dict):
raise
errors.extend(exc.detail)
except DjangoValidationError as exc:
errors.extend(get_error_detail(exc))
if errors:
raise ValidationError(errors)
def
save(self, **kwargs):
¶
BaseSerializer
def save(self, **kwargs):
assert not hasattr(self, 'save_object'), (
'Serializer `%s.%s` has old-style version 2 `.save_object()` '
'that is no longer compatible with REST framework 3. '
'Use the new-style `.create()` and `.update()` methods instead.' %
(self.__class__.__module__, self.__class__.__name__)
)
assert hasattr(self, '_errors'), (
'You must call `.is_valid()` before calling `.save()`.'
)
assert not self.errors, (
'You cannot call `.save()` on a serializer with invalid data.'
)
# Guard against incorrect use of `serializer.save(commit=False)`
assert 'commit' not in kwargs, (
"'commit' is not a valid keyword argument to the 'save()' method. "
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
"You can also pass additional keyword arguments to 'save()' if you "
"need to set extra attributes on the saved model instance. "
"For example: 'serializer.save(owner=request.user)'.'"
)
assert not hasattr(self, '_data'), (
"You cannot call `.save()` after accessing `serializer.data`."
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
)
validated_data = dict(
list(self.validated_data.items()) +
list(kwargs.items())
)
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
assert self.instance is not None, (
'`update()` did not return an object instance.'
)
else:
self.instance = self.create(validated_data)
assert self.instance is not None, (
'`create()` did not return an object instance.'
)
return self.instance
def
to_internal_value(self, data):
¶
Serializer
Dict of native values <- Dict of primitive datatypes.
def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, Mapping):
message = self.error_messages['invalid'].format(
datatype=type(data).__name__
)
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message]
}, code='invalid')
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
for field in fields:
validate_method = getattr(self, 'validate_' + field.field_name, None)
primitive_value = field.get_value(data)
try:
validated_value = field.run_validation(primitive_value)
if validate_method is not None:
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = get_error_detail(exc)
except SkipField:
pass
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
BaseSerializer
def to_internal_value(self, data):
raise NotImplementedError('`to_internal_value()` must be implemented.')
Field
Transform the *incoming* primitive data into a native value.
def to_internal_value(self, data):
"""
Transform the *incoming* primitive data into a native value.
"""
raise NotImplementedError(
'{cls}.to_internal_value() must be implemented.'.format(
cls=self.__class__.__name__
)
)
def
to_representation(self, instance):
¶
Serializer
Object instance -> Dict of primitive datatypes.
def to_representation(self, instance):
"""
Object instance -> Dict of primitive datatypes.
"""
ret = OrderedDict()
fields = self._readable_fields
for field in fields:
try:
attribute = field.get_attribute(instance)
except SkipField:
continue
# We skip `to_representation` for `None` values so that fields do
# not have to explicitly deal with that case.
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
ret[field.field_name] = None
else:
ret[field.field_name] = field.to_representation(attribute)
return ret
BaseSerializer
def to_representation(self, instance):
raise NotImplementedError('`to_representation()` must be implemented.')
Field
Transform the *outgoing* native value into primitive data.
def to_representation(self, value):
"""
Transform the *outgoing* native value into primitive data.
"""
raise NotImplementedError(
'{cls}.to_representation() must be implemented for field '
'{field_name}. If you do not need to support write operations '
'you probably want to subclass `ReadOnlyField` instead.'.format(
cls=self.__class__.__name__,
field_name=self.field_name,
)
)
def
update(self, instance, validated_data):
¶
BaseSerializer
def update(self, instance, validated_data):
raise NotImplementedError('`update()` must be implemented.')
def
validate(self, attrs):
¶
Serializer
def validate(self, attrs):
return attrs
def
validate_empty_values(self, data):
¶
Field
Validate empty values, and either: * Raise `ValidationError`, indicating invalid data. * Raise `SkipField`, indicating that the field should be ignored. * Return (True, data), indicating an empty value that should be returned without any further validation being applied. * Return (False, data), indicating a non-empty value, that should have validation applied as normal.
def validate_empty_values(self, data):
"""
Validate empty values, and either:
* Raise `ValidationError`, indicating invalid data.
* Raise `SkipField`, indicating that the field should be ignored.
* Return (True, data), indicating an empty value that should be
returned without any further validation being applied.
* Return (False, data), indicating a non-empty value, that should
have validation applied as normal.
"""
if self.read_only:
return (True, self.get_default())
if data is empty:
if getattr(self.root, 'partial', False):
raise SkipField()
if self.required:
self.fail('required')
return (True, self.get_default())
if data is None:
if not self.allow_null:
self.fail('null')
return (True, None)
return (False, data)