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.style = {} if style is None else style
|
||||
self.allow_null = allow_null
|
||||
self.is_bound = False
|
||||
|
||||
if self.default_empty_html 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.
|
||||
"""
|
||||
|
||||
if self.is_bound:
|
||||
return
|
||||
|
||||
# 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')
|
||||
|
@ -331,6 +335,8 @@ class Field(object):
|
|||
else:
|
||||
self.source_attrs = self.source.split('.')
|
||||
|
||||
self.is_bound = True
|
||||
|
||||
# .validators is a lazily loaded property, that gets its default
|
||||
# value from `get_validators`.
|
||||
@property
|
||||
|
|
|
@ -493,6 +493,11 @@ class Serializer(BaseSerializer):
|
|||
return ReturnDict(ret, serializer=self)
|
||||
|
||||
|
||||
class ImmutableSerializer(Serializer):
|
||||
def get_fields(self):
|
||||
return self._declared_fields
|
||||
|
||||
|
||||
# There's some replication of `ListField` here,
|
||||
# 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
|
||||
# "HTTP 201 Created" responses.
|
||||
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...
|
||||
def create(self, validated_data):
|
||||
|
@ -864,11 +875,7 @@ class ModelSerializer(Serializer):
|
|||
|
||||
# Determine the fields to apply...
|
||||
|
||||
def get_fields(self):
|
||||
"""
|
||||
Return the dict of field names -> field instances that should be
|
||||
used for `self.fields` when instantiating the serializer.
|
||||
"""
|
||||
def _validate_serializer_meta(self):
|
||||
assert hasattr(self, 'Meta'), (
|
||||
'Class {serializer_class} missing "Meta" attribute'.format(
|
||||
serializer_class=self.__class__.__name__
|
||||
|
@ -884,14 +891,14 @@ class ModelSerializer(Serializer):
|
|||
'Cannot use ModelSerializer with Abstract Models.'
|
||||
)
|
||||
|
||||
declared_fields = copy.deepcopy(self._declared_fields)
|
||||
model = getattr(self.Meta, 'model')
|
||||
depth = getattr(self.Meta, 'depth', 0)
|
||||
|
||||
depth = self._depth
|
||||
if depth is not None:
|
||||
assert depth >= 0, "'depth' may not be negative."
|
||||
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.
|
||||
info = model_meta.get_field_info(model)
|
||||
field_names = self.get_field_names(declared_fields, info)
|
||||
|
@ -928,6 +935,16 @@ class ModelSerializer(Serializer):
|
|||
|
||||
# Add in any 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
|
||||
|
||||
|
@ -1382,6 +1399,14 @@ class ModelSerializer(Serializer):
|
|||
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'):
|
||||
ModelSerializer.serializer_field_mapping[models.UUIDField] = UUIDField
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user