mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-08 06:14:47 +03:00
Added immutable serializers that skips deep copying fields and also skips binding them again since they are already bound.
This commit is contained in:
parent
1b53e804ee
commit
3e9b9f3efd
|
@ -278,6 +278,7 @@ class Field(object):
|
||||||
self.help_text = help_text
|
self.help_text = help_text
|
||||||
self.style = {} if style is None else style
|
self.style = {} if style is None else style
|
||||||
self.allow_null = allow_null
|
self.allow_null = allow_null
|
||||||
|
self.is_bound = False
|
||||||
|
|
||||||
if self.default_empty_html is not empty:
|
if self.default_empty_html is not empty:
|
||||||
if default is not empty:
|
if default is not empty:
|
||||||
|
@ -303,6 +304,9 @@ class Field(object):
|
||||||
Called when a field is added to the parent serializer instance.
|
Called when a field is added to the parent serializer instance.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if self.is_bound:
|
||||||
|
return
|
||||||
|
|
||||||
# In order to enforce a consistent style, we error if a redundant
|
# In order to enforce a consistent style, we error if a redundant
|
||||||
# 'source' argument has been used. For example:
|
# 'source' argument has been used. For example:
|
||||||
# my_field = serializer.CharField(source='my_field')
|
# my_field = serializer.CharField(source='my_field')
|
||||||
|
@ -331,6 +335,8 @@ class Field(object):
|
||||||
else:
|
else:
|
||||||
self.source_attrs = self.source.split('.')
|
self.source_attrs = self.source.split('.')
|
||||||
|
|
||||||
|
self.is_bound = True
|
||||||
|
|
||||||
# .validators is a lazily loaded property, that gets its default
|
# .validators is a lazily loaded property, that gets its default
|
||||||
# value from `get_validators`.
|
# value from `get_validators`.
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -493,6 +493,11 @@ class Serializer(BaseSerializer):
|
||||||
return ReturnDict(ret, serializer=self)
|
return ReturnDict(ret, serializer=self)
|
||||||
|
|
||||||
|
|
||||||
|
class ImmutableSerializer(Serializer):
|
||||||
|
def get_fields(self):
|
||||||
|
return self._declared_fields
|
||||||
|
|
||||||
|
|
||||||
# There's some replication of `ListField` here,
|
# There's some replication of `ListField` here,
|
||||||
# but that's probably better than obfuscating the call hierarchy.
|
# but that's probably better than obfuscating the call hierarchy.
|
||||||
|
|
||||||
|
@ -787,6 +792,12 @@ class ModelSerializer(Serializer):
|
||||||
# views, to correctly handle the 'Location' response header for
|
# views, to correctly handle the 'Location' response header for
|
||||||
# "HTTP 201 Created" responses.
|
# "HTTP 201 Created" responses.
|
||||||
url_field_name = api_settings.URL_FIELD_NAME
|
url_field_name = api_settings.URL_FIELD_NAME
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def _depth(self):
|
||||||
|
return getattr(self.Meta, 'depth', 0)
|
||||||
|
|
||||||
|
# Default `create` and `update` behavior...
|
||||||
|
|
||||||
# Default `create` and `update` behavior...
|
# Default `create` and `update` behavior...
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
@ -864,11 +875,7 @@ class ModelSerializer(Serializer):
|
||||||
|
|
||||||
# Determine the fields to apply...
|
# Determine the fields to apply...
|
||||||
|
|
||||||
def get_fields(self):
|
def _validate_serializer_meta(self):
|
||||||
"""
|
|
||||||
Return the dict of field names -> field instances that should be
|
|
||||||
used for `self.fields` when instantiating the serializer.
|
|
||||||
"""
|
|
||||||
assert hasattr(self, 'Meta'), (
|
assert hasattr(self, 'Meta'), (
|
||||||
'Class {serializer_class} missing "Meta" attribute'.format(
|
'Class {serializer_class} missing "Meta" attribute'.format(
|
||||||
serializer_class=self.__class__.__name__
|
serializer_class=self.__class__.__name__
|
||||||
|
@ -884,14 +891,14 @@ class ModelSerializer(Serializer):
|
||||||
'Cannot use ModelSerializer with Abstract Models.'
|
'Cannot use ModelSerializer with Abstract Models.'
|
||||||
)
|
)
|
||||||
|
|
||||||
declared_fields = copy.deepcopy(self._declared_fields)
|
depth = self._depth
|
||||||
model = getattr(self.Meta, 'model')
|
|
||||||
depth = getattr(self.Meta, 'depth', 0)
|
|
||||||
|
|
||||||
if depth is not None:
|
if depth is not None:
|
||||||
assert depth >= 0, "'depth' may not be negative."
|
assert depth >= 0, "'depth' may not be negative."
|
||||||
assert depth <= 10, "'depth' may not be greater than 10."
|
assert depth <= 10, "'depth' may not be greater than 10."
|
||||||
|
|
||||||
|
def _get_serializer_fields_from_declared_fields(self, declared_fields, depth):
|
||||||
|
model = getattr(self.Meta, 'model')
|
||||||
|
|
||||||
# Retrieve metadata about fields & relationships on the model class.
|
# Retrieve metadata about fields & relationships on the model class.
|
||||||
info = model_meta.get_field_info(model)
|
info = model_meta.get_field_info(model)
|
||||||
field_names = self.get_field_names(declared_fields, info)
|
field_names = self.get_field_names(declared_fields, info)
|
||||||
|
@ -928,6 +935,16 @@ class ModelSerializer(Serializer):
|
||||||
|
|
||||||
# Add in any hidden fields.
|
# Add in any hidden fields.
|
||||||
fields.update(hidden_fields)
|
fields.update(hidden_fields)
|
||||||
|
return fields
|
||||||
|
|
||||||
|
def get_fields(self):
|
||||||
|
"""
|
||||||
|
Return the dict of field names -> field instances that should be
|
||||||
|
used for `self.fields` when instantiating the serializer.
|
||||||
|
"""
|
||||||
|
self._validate_serializer_meta()
|
||||||
|
declared_fields = copy.deepcopy(self._declared_fields)
|
||||||
|
fields = self._get_serializer_fields_from_declared_fields(declared_fields, self._depth)
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
@ -1382,6 +1399,14 @@ class ModelSerializer(Serializer):
|
||||||
return validators
|
return validators
|
||||||
|
|
||||||
|
|
||||||
|
class ImmutableModelSerializer(ModelSerializer):
|
||||||
|
def get_fields(self):
|
||||||
|
self._validate_serializer_meta()
|
||||||
|
fields = self._get_serializer_fields_from_declared_fields(self._declared_fields, self._depth)
|
||||||
|
|
||||||
|
return fields
|
||||||
|
|
||||||
|
|
||||||
if hasattr(models, 'UUIDField'):
|
if hasattr(models, 'UUIDField'):
|
||||||
ModelSerializer.serializer_field_mapping[models.UUIDField] = UUIDField
|
ModelSerializer.serializer_field_mapping[models.UUIDField] = UUIDField
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user