mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-03-20 01:44:14 +03:00
Allow many, partial and context in BaseSerializer
This commit is contained in:
parent
fde934d33c
commit
8b8623c5f8
|
@ -2,6 +2,13 @@
|
|||
|
||||
See the [Version 3.0 GitHub issue](https://github.com/tomchristie/django-rest-framework/pull/1800) for more details.
|
||||
|
||||
Most notable outstanding issues still to resolved on the `version-3.0` branch.
|
||||
|
||||
* `FileField` and `ImageField` support.
|
||||
* Forms support for serializers and in the browsable API.
|
||||
* Enforcing uniqueness on `unique=True` and `unique_together` fields.
|
||||
* Optimisations for serialializing primary keys.
|
||||
|
||||
# REST framework 3.0
|
||||
|
||||
The 3.0 release of Django REST framework is the result of almost four years of iteration and refinement. It comprehensively addresses some of the previous remaining design issues in serializers, fields and the generic views.
|
||||
|
|
|
@ -47,9 +47,20 @@ class BaseSerializer(Field):
|
|||
"""
|
||||
|
||||
def __init__(self, instance=None, data=None, **kwargs):
|
||||
super(BaseSerializer, self).__init__(**kwargs)
|
||||
self.instance = instance
|
||||
self._initial_data = data
|
||||
self.partial = kwargs.pop('partial', False)
|
||||
self._context = kwargs.pop('context', {})
|
||||
kwargs.pop('many', None)
|
||||
super(BaseSerializer, self).__init__(**kwargs)
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
# We override this method in order to automagically create
|
||||
# `ListSerializer` classes instead when `many=True` is set.
|
||||
if kwargs.pop('many', False):
|
||||
kwargs['child'] = cls()
|
||||
return ListSerializer(*args, **kwargs)
|
||||
return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)
|
||||
|
||||
def to_internal_value(self, data):
|
||||
raise NotImplementedError('`to_internal_value()` must be implemented.')
|
||||
|
@ -187,10 +198,6 @@ class BindingDict(object):
|
|||
@six.add_metaclass(SerializerMetaclass)
|
||||
class Serializer(BaseSerializer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.pop('many', None)
|
||||
self.partial = kwargs.pop('partial', False)
|
||||
self._context = kwargs.pop('context', {})
|
||||
|
||||
super(Serializer, self).__init__(*args, **kwargs)
|
||||
|
||||
# Every new serializer is created with a clone of the field instances.
|
||||
|
@ -200,14 +207,6 @@ class Serializer(BaseSerializer):
|
|||
for key, value in self._get_base_fields().items():
|
||||
self.fields[key] = value
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
# We override this method in order to automagically create
|
||||
# `ListSerializer` classes instead when `many=True` is set.
|
||||
if kwargs.pop('many', False):
|
||||
kwargs['child'] = cls()
|
||||
return ListSerializer(*args, **kwargs)
|
||||
return super(Serializer, cls).__new__(cls, *args, **kwargs)
|
||||
|
||||
def _get_base_fields(self):
|
||||
return copy.deepcopy(self._declared_fields)
|
||||
|
||||
|
@ -296,9 +295,6 @@ class ListSerializer(BaseSerializer):
|
|||
self.child = kwargs.pop('child', copy.deepcopy(self.child))
|
||||
assert self.child is not None, '`child` is a required argument.'
|
||||
assert not inspect.isclass(self.child), '`child` has not been instantiated.'
|
||||
self.partial = kwargs.pop('partial', False)
|
||||
self._context = kwargs.pop('context', {})
|
||||
|
||||
super(ListSerializer, self).__init__(*args, **kwargs)
|
||||
self.child.bind(field_name='', parent=self)
|
||||
|
||||
|
|
|
@ -43,6 +43,64 @@ class TestSerializer:
|
|||
serializer.data
|
||||
|
||||
|
||||
class TestBaseSerializer:
|
||||
def setup(self):
|
||||
class ExampleSerializer(serializers.BaseSerializer):
|
||||
def to_representation(self, obj):
|
||||
return {
|
||||
'id': obj['id'],
|
||||
'email': obj['name'] + '@' + obj['domain']
|
||||
}
|
||||
|
||||
def to_internal_value(self, data):
|
||||
name, domain = str(data['email']).split('@')
|
||||
return {
|
||||
'id': int(data['id']),
|
||||
'name': name,
|
||||
'domain': domain,
|
||||
}
|
||||
|
||||
self.Serializer = ExampleSerializer
|
||||
|
||||
def test_serialize_instance(self):
|
||||
instance = {'id': 1, 'name': 'tom', 'domain': 'example.com'}
|
||||
serializer = self.Serializer(instance)
|
||||
assert serializer.data == {'id': 1, 'email': 'tom@example.com'}
|
||||
|
||||
def test_serialize_list(self):
|
||||
instances = [
|
||||
{'id': 1, 'name': 'tom', 'domain': 'example.com'},
|
||||
{'id': 2, 'name': 'ann', 'domain': 'example.com'},
|
||||
]
|
||||
serializer = self.Serializer(instances, many=True)
|
||||
assert serializer.data == [
|
||||
{'id': 1, 'email': 'tom@example.com'},
|
||||
{'id': 2, 'email': 'ann@example.com'}
|
||||
]
|
||||
|
||||
def test_validate_data(self):
|
||||
data = {'id': 1, 'email': 'tom@example.com'}
|
||||
serializer = self.Serializer(data=data)
|
||||
assert serializer.is_valid()
|
||||
assert serializer.validated_data == {
|
||||
'id': 1,
|
||||
'name': 'tom',
|
||||
'domain': 'example.com'
|
||||
}
|
||||
|
||||
def test_validate_list(self):
|
||||
data = [
|
||||
{'id': 1, 'email': 'tom@example.com'},
|
||||
{'id': 2, 'email': 'ann@example.com'},
|
||||
]
|
||||
serializer = self.Serializer(data=data, many=True)
|
||||
assert serializer.is_valid()
|
||||
assert serializer.validated_data == [
|
||||
{'id': 1, 'name': 'tom', 'domain': 'example.com'},
|
||||
{'id': 2, 'name': 'ann', 'domain': 'example.com'}
|
||||
]
|
||||
|
||||
|
||||
class TestStarredSource:
|
||||
"""
|
||||
Tests for `source='*'` argument, which is used for nested representations.
|
||||
|
|
Loading…
Reference in New Issue
Block a user