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
This commit is contained in:
Steven Cummings 2013-12-12 22:36:19 -06:00
parent 0e8760eaaf
commit b0027e52fa
3 changed files with 72 additions and 76 deletions

View File

@ -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

View File

@ -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()
}

View File

@ -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.
"""