mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-23 15:54:16 +03:00
Allow serializers to handle dicts as well as objects. Fixes #447.
This commit is contained in:
parent
8113d66126
commit
670ac25b25
|
@ -29,6 +29,7 @@ You can determine your currently installed version using `pip freeze`:
|
|||
### Master
|
||||
|
||||
* Added a `post_save()` hook to the generic views.
|
||||
* Allow serializers to handle dicts as well as objects.
|
||||
* Bugfix: Fix styling on browsable API login.
|
||||
* Bugfix: Fix issue with deserializing empty to-many relations.
|
||||
* Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method.
|
||||
|
|
|
@ -30,6 +30,21 @@ def is_simple_callable(obj):
|
|||
)
|
||||
|
||||
|
||||
def get_component(obj, attr_name):
|
||||
"""
|
||||
Given an object, and an attribute name,
|
||||
return that attribute on the object.
|
||||
"""
|
||||
if isinstance(obj, dict):
|
||||
val = obj[attr_name]
|
||||
else:
|
||||
val = getattr(obj, attr_name)
|
||||
|
||||
if is_simple_callable(val):
|
||||
return val()
|
||||
return val
|
||||
|
||||
|
||||
class Field(object):
|
||||
read_only = True
|
||||
creation_counter = 0
|
||||
|
@ -82,11 +97,9 @@ class Field(object):
|
|||
if self.source:
|
||||
value = obj
|
||||
for component in self.source.split('.'):
|
||||
value = getattr(value, component)
|
||||
if is_simple_callable(value):
|
||||
value = value()
|
||||
value = get_component(value, component)
|
||||
else:
|
||||
value = getattr(obj, field_name)
|
||||
value = get_component(obj, field_name)
|
||||
return self.to_native(value)
|
||||
|
||||
def to_native(self, value):
|
||||
|
|
|
@ -325,7 +325,7 @@ class BaseSerializer(Field):
|
|||
if self.many is not None:
|
||||
many = self.many
|
||||
else:
|
||||
many = hasattr(obj, '__iter__') and not isinstance(obj, Page)
|
||||
many = hasattr(obj, '__iter__') and not isinstance(obj, (Page, dict))
|
||||
|
||||
if many:
|
||||
return [self.to_native(item) for item in obj]
|
||||
|
@ -343,7 +343,7 @@ class BaseSerializer(Field):
|
|||
if self.many is not None:
|
||||
many = self.many
|
||||
else:
|
||||
many = hasattr(data, '__iter__') and not isinstance(data, dict)
|
||||
many = hasattr(data, '__iter__') and not isinstance(data, (Page, dict))
|
||||
|
||||
# TODO: error data when deserializing lists
|
||||
if many:
|
||||
|
@ -368,7 +368,7 @@ class BaseSerializer(Field):
|
|||
if self.many is not None:
|
||||
many = self.many
|
||||
else:
|
||||
many = hasattr(obj, '__iter__') and not isinstance(obj, Page)
|
||||
many = hasattr(obj, '__iter__') and not isinstance(obj, (Page, dict))
|
||||
|
||||
if many:
|
||||
self._data = [self.to_native(item) for item in obj]
|
||||
|
|
|
@ -185,6 +185,33 @@ class BasicTests(TestCase):
|
|||
self.assertEquals(instance.age, self.person_data['age'])
|
||||
|
||||
|
||||
class DictStyleSerializer(serializers.Serializer):
|
||||
"""
|
||||
Note that we don't have any `restore_object` method, so the default
|
||||
case of simply returning a dict will apply.
|
||||
"""
|
||||
email = serializers.EmailField()
|
||||
|
||||
|
||||
class DictStyleSerializerTests(TestCase):
|
||||
def test_dict_style_deserialize(self):
|
||||
"""
|
||||
Ensure serializers can deserialize into a dict.
|
||||
"""
|
||||
data = {'email': 'foo@example.com'}
|
||||
serializer = DictStyleSerializer(data=data)
|
||||
self.assertTrue(serializer.is_valid())
|
||||
self.assertEquals(serializer.data, data)
|
||||
|
||||
def test_dict_style_serialize(self):
|
||||
"""
|
||||
Ensure serializers can serialize dict objects.
|
||||
"""
|
||||
data = {'email': 'foo@example.com'}
|
||||
serializer = DictStyleSerializer(data)
|
||||
self.assertEquals(serializer.data, data)
|
||||
|
||||
|
||||
class ValidationTests(TestCase):
|
||||
def setUp(self):
|
||||
self.comment = Comment(
|
||||
|
|
Loading…
Reference in New Issue
Block a user