From 9b19b5a59485c9dad4a18538a8a86f1ae4ea2a55 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 7 Nov 2014 10:13:46 +0000 Subject: Serializer cleanup --- rest_framework/utils/serializer_helpers.py | 99 ++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 rest_framework/utils/serializer_helpers.py (limited to 'rest_framework/utils/serializer_helpers.py') diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py new file mode 100644 index 00000000..a861ca07 --- /dev/null +++ b/rest_framework/utils/serializer_helpers.py @@ -0,0 +1,99 @@ +from rest_framework.compat import OrderedDict + + +class ReturnDict(OrderedDict): + """ + Return object from `serialier.data` for the `Serializer` class. + Includes a backlink to the serializer instance for renderers + to use if they need richer field information. + """ + def __init__(self, *args, **kwargs): + self.serializer = kwargs.pop('serializer') + super(ReturnDict, self).__init__(*args, **kwargs) + + +class ReturnList(list): + """ + Return object from `serialier.data` for the `SerializerList` class. + Includes a backlink to the serializer instance for renderers + to use if they need richer field information. + """ + def __init__(self, *args, **kwargs): + self.serializer = kwargs.pop('serializer') + super(ReturnList, self).__init__(*args, **kwargs) + + +class BoundField(object): + """ + A field object that also includes `.value` and `.error` properties. + Returned when iterating over a serializer instance, + providing an API similar to Django forms and form fields. + """ + def __init__(self, field, value, errors, prefix=''): + self._field = field + self.value = value + self.errors = errors + self.name = prefix + self.field_name + + def __getattr__(self, attr_name): + return getattr(self._field, attr_name) + + @property + def _proxy_class(self): + return self._field.__class__ + + def __repr__(self): + return '<%s value=%s errors=%s>' % ( + self.__class__.__name__, self.value, self.errors + ) + + +class NestedBoundField(BoundField): + """ + This `BoundField` additionally implements __iter__ and __getitem__ + in order to support nested bound fields. This class is the type of + `BoundField` that is used for serializer fields. + """ + def __iter__(self): + for field in self.fields.values(): + yield self[field.field_name] + + def __getitem__(self, key): + field = self.fields[key] + value = self.value.get(key) if self.value else None + error = self.errors.get(key) if self.errors else None + if hasattr(field, 'fields'): + return NestedBoundField(field, value, error, prefix=self.name + '.') + return BoundField(field, value, error, prefix=self.name + '.') + + +class BindingDict(object): + """ + 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 items(self): + return self.fields.items() + + def keys(self): + return self.fields.keys() + + def values(self): + return self.fields.values() -- cgit v1.2.3 From a16a8a10a9204e574ad912eeced535d70a385b37 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 7 Nov 2014 11:16:26 +0000 Subject: .copy() for serializer .data and .errors dictionaries --- rest_framework/utils/serializer_helpers.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'rest_framework/utils/serializer_helpers.py') diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index a861ca07..92d19857 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -11,6 +11,9 @@ class ReturnDict(OrderedDict): self.serializer = kwargs.pop('serializer') super(ReturnDict, self).__init__(*args, **kwargs) + def copy(self): + return ReturnDict(self, serializer=self.serializer) + class ReturnList(list): """ -- cgit v1.2.3