Replace usage of BindingDict and remove it

BindingDict ensures that .bind() is called on each field. However this
is easily ensured without it.

One thing that BindingDict might have helped with is to ensure .bind()
is called even if a field is added after the fact to the dict,
externally. However such use is already broken since _readable_fields
and _writable fields use the fields and are cached. Doing so sounds like
a bad idea, anyway.
This commit is contained in:
Ran Benita 2019-05-09 09:24:54 +03:00
parent 1b8141a4aa
commit 68eb863e7c
2 changed files with 5 additions and 39 deletions

View File

@ -36,8 +36,7 @@ from rest_framework.utils.field_mapping import (
get_relation_kwargs, get_url_kwargs get_relation_kwargs, get_url_kwargs
) )
from rest_framework.utils.serializer_helpers import ( from rest_framework.utils.serializer_helpers import (
BindingDict, BoundField, JSONBoundField, NestedBoundField, ReturnDict, BoundField, JSONBoundField, NestedBoundField, ReturnDict, ReturnList
ReturnList
) )
from rest_framework.validators import ( from rest_framework.validators import (
UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator, UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator,
@ -356,9 +355,10 @@ class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
# `fields` is evaluated lazily. We do this to ensure that we don't # `fields` is evaluated lazily. We do this to ensure that we don't
# have issues importing modules that use ModelSerializers as fields, # have issues importing modules that use ModelSerializers as fields,
# even if Django's app-loading stage has not yet run. # even if Django's app-loading stage has not yet run.
fields = BindingDict(self) fields = OrderedDict()
for key, value in self.get_fields().items(): for field_name, field in self.get_fields().items():
fields[key] = value fields[field_name] = field
field.bind(field_name=field_name, parent=self)
return fields return fields
@cached_property @cached_property

View File

@ -1,5 +1,4 @@
from collections import OrderedDict from collections import OrderedDict
from collections.abc import MutableMapping
from django.utils.encoding import force_text from django.utils.encoding import force_text
@ -125,36 +124,3 @@ class NestedBoundField(BoundField):
else: else:
values[key] = '' if (value is None or value is False) else force_text(value) values[key] = '' if (value is None or value is False) else force_text(value)
return self.__class__(self._field, values, self.errors, self._prefix) return self.__class__(self._field, values, self.errors, self._prefix)
class BindingDict(MutableMapping):
"""
This dict-like object is used to store fields on a serializer.
This ensures that whenever fields are added to the serializer we call
`field.bind()` so that the `field_name` and `parent` attributes
can be set correctly.
"""
def __init__(self, serializer):
self.serializer = serializer
self.fields = OrderedDict()
def __setitem__(self, key, field):
self.fields[key] = field
field.bind(field_name=key, parent=self.serializer)
def __getitem__(self, key):
return self.fields[key]
def __delitem__(self, key):
del self.fields[key]
def __iter__(self):
return iter(self.fields)
def __len__(self):
return len(self.fields)
def __repr__(self):
return dict.__repr__(self.fields)