diff --git a/rest_framework/fields.py b/rest_framework/fields.py index f1de447c7..73d792749 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1012,3 +1012,78 @@ 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 8351b3df6..27db7b962 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): + def from_native(self, data, files=None): """ Deserialize primitives -> objects. """