From b0027e52fa3efead56452fff87dc2dc2a8e2d936 Mon Sep 17 00:00:00 2001 From: Steven Cummings Date: Thu, 12 Dec 2013 22:36:19 -0600 Subject: [PATCH] Updates for pull request review comments * Remove ListOrObjectField * Allow item_field & value_field to be optional * Undo from_native API change; flex invocation in compound fields * In DictField, coerce key to a string * If list or dict is None or empty, just return input preserving empty containers * Remove dict comprehension for Python 2.6 compat --- rest_framework/compound_fields.py | 71 +++++++++++++++++++++++++++++ rest_framework/fields.py | 75 ------------------------------- rest_framework/serializers.py | 2 +- 3 files changed, 72 insertions(+), 76 deletions(-) create mode 100644 rest_framework/compound_fields.py diff --git a/rest_framework/compound_fields.py b/rest_framework/compound_fields.py new file mode 100644 index 000000000..cbdb95988 --- /dev/null +++ b/rest_framework/compound_fields.py @@ -0,0 +1,71 @@ +""" +Compound fields for processing values that are lists and dicts of values described by embedded +fields. +""" +from .fields import WritableField +from .serializers import BaseSerializer + + +def field_or_serializer_from_native(field_or_serializer, data): + if isinstance(field_or_serializer, BaseSerializer): + return field_or_serializer.from_native(data, None) + return field_or_serializer.from_native(data) + + +class ListField(WritableField): + """ + A field whose values are lists of items described by the given item field. The item field can + be another field type (e.g., CharField) or a serializer. + """ + + def __init__(self, item_field=None, *args, **kwargs): + super(ListField, self).__init__(*args, **kwargs) + self.item_field = item_field + + def to_native(self, obj): + if obj: + return [ + self.item_field.to_native(item) if self.item_field else item + for item in obj + ] + return obj + + def from_native(self, data): + if data: + return [ + field_or_serializer_from_native(self.item_field, item_data) + if self.item_field else item_data + for item_data in data + ] + return data + + +class DictField(WritableField): + """ + A field whose values are dicts of values described by the given value field. The value field + can be another field type (e.g., CharField) or a serializer. + """ + + def __init__(self, value_field=None, *args, **kwargs): + super(DictField, self).__init__(*args, **kwargs) + self.value_field = value_field + + def to_native(self, obj): + if obj: + return dict( + (key, self.value_field.to_native(value) if self.value_field else value) + for key, value in obj.items() + ) + return obj + + def from_native(self, data): + if data: + return dict( + ( + unicode(key), + field_or_serializer_from_native(self.value_field, value) + if self.value_field else value + ) + for key, value in data.items() + ) + return data diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 73d792749..f1de447c7 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1012,78 +1012,3 @@ class SerializerMethodField(Field): def field_to_native(self, obj, field_name): value = getattr(self.parent, self.method_name)(obj) return self.to_native(value) - - -##### Compound Typed Fields ##### - - -class ListField(WritableField): - """ - A field whose values are lists of items described by the given item field. The item field can - be another field type (e.g., CharField) or a serializer. - """ - - def __init__(self, item_field, *args, **kwargs): - super(ListField, self).__init__(*args, **kwargs) - self.item_field = item_field - - def to_native(self, obj): - if obj: - return [ - self.item_field.to_native(item) - for item in obj - ] - - def from_native(self, data): - if data: - return [ - self.item_field.from_native(item_data) - for item_data in data - ] - - -class ListOrObjectField(WritableField): - """ - A field whose values are either objects or lists of items described by the given item field. - The item field can be another field type (e.g., CharField) or a serializer. - """ - - def __init__(self, item_field, *args, **kwargs): - super(ListOrObjectField, self).__init__(*args, **kwargs) - self.item_field = item_field - self.list_field = ListField(item_field) - - def to_native(self, obj): - if isinstance(obj, list): - return self.list_field.to_native(obj) - return self.item_field.to_native(obj) - - def from_native(self, data): - if isinstance(obj, list): - return self.list_field.from_native(obj) - return self.item_field.from_native(obj) - - -class DictField(WritableField): - """ - A field whose values are dicts of values described by the given value field. The value field - can be another field type (e.g., CharField) or a serializer. - """ - - def __init__(self, value_field, *args, **kwargs): - super(DictField, self).__init__(*args, **kwargs) - self.value_field = value_field - - def to_native(self, obj): - if obj: - return { - key:self.value_field.to_native(value) - for key, value in obj.items() - } - - def from_native(self, data): - if data: - return { - key:self.value_field.from_native(value) - for key, value in data.items() - } diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 27db7b962..8351b3df6 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -331,7 +331,7 @@ class BaseSerializer(WritableField): return ret - def from_native(self, data, files=None): + def from_native(self, data, files): """ Deserialize primitives -> objects. """