mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-06 13:30:12 +03:00
alternative approach that allows for validation
This commit is contained in:
parent
c6d44789e2
commit
09aff6daeb
|
@ -1156,6 +1156,9 @@ class ListField(Field):
|
||||||
self.child = kwargs.pop('child', copy.deepcopy(self.child))
|
self.child = kwargs.pop('child', copy.deepcopy(self.child))
|
||||||
assert not inspect.isclass(self.child), '`child` has not been instantiated.'
|
assert not inspect.isclass(self.child), '`child` has not been instantiated.'
|
||||||
super(ListField, self).__init__(*args, **kwargs)
|
super(ListField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def bind(self, field_name, parent):
|
||||||
|
super(ListField, self).bind(field_name, parent)
|
||||||
self.child.bind(field_name='', parent=self)
|
self.child.bind(field_name='', parent=self)
|
||||||
|
|
||||||
def get_value(self, dictionary):
|
def get_value(self, dictionary):
|
||||||
|
@ -1290,24 +1293,41 @@ class RecursiveField(Field):
|
||||||
next = RecursiveField(allow_null=True)
|
next = RecursiveField(allow_null=True)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
kwargz = {'required': False}
|
field_kwargs = dict(
|
||||||
kwargz.update(kwargs)
|
(key, value)
|
||||||
super(RecursiveField, self).__init__(*args, **kwargz)
|
for key in kwargs
|
||||||
|
if key in inspect.getargspec(Field.__init__)
|
||||||
|
)
|
||||||
|
super(RecursiveField, self).__init__(**field_kwargs)
|
||||||
|
|
||||||
def _get_parent(self):
|
def bind(self, field_name, parent):
|
||||||
if hasattr(self.parent, 'child') and self.parent.child is self:
|
super(RecursiveField, self).bind(field_name, parent)
|
||||||
# Recursive field nested inside of some kind of composite list field
|
|
||||||
return self.parent.parent
|
real_dict = object.__getattribute__(self, '__dict__')
|
||||||
|
|
||||||
|
if hasattr(parent, 'child') and parent.child is self:
|
||||||
|
proxy_class = parent.parent.__class__
|
||||||
else:
|
else:
|
||||||
return self.parent
|
proxy_class = parent.__class__
|
||||||
|
|
||||||
def to_representation(self, value):
|
proxy = proxy_class(**self._kwargs)
|
||||||
return self._get_parent().to_representation(value)
|
proxy.bind(field_name, parent)
|
||||||
|
real_dict['proxy'] = proxy
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def __getattribute__(self, name):
|
||||||
return self._get_parent().to_internal_value(data)
|
real_dict = object.__getattribute__(self, '__dict__')
|
||||||
|
if 'proxy' in real_dict and name != 'fields' and not (name.startswith('__') and name.endswith('__')):
|
||||||
|
return object.__getattribute__(real_dict['proxy'], name)
|
||||||
|
else:
|
||||||
|
return object.__getattribute__(self, name)
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
real_dict = object.__getattribute__(self, '__dict__')
|
||||||
|
if 'proxy' in real_dict:
|
||||||
|
setattr(real_dict['proxy'], name, value)
|
||||||
|
else:
|
||||||
|
real_dict[name] = value
|
||||||
|
|
||||||
class SerializerMethodField(Field):
|
class SerializerMethodField(Field):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -300,7 +300,7 @@ class TestRecursiveField:
|
||||||
def setup(self):
|
def setup(self):
|
||||||
class LinkSerializer(serializers.Serializer):
|
class LinkSerializer(serializers.Serializer):
|
||||||
name = serializers.CharField()
|
name = serializers.CharField()
|
||||||
next = serializers.RecursiveField(allow_null=True)
|
next = serializers.RecursiveField(required=False, allow_null=True)
|
||||||
self.link_serializer = LinkSerializer
|
self.link_serializer = LinkSerializer
|
||||||
|
|
||||||
class NodeSerializer(serializers.Serializer):
|
class NodeSerializer(serializers.Serializer):
|
||||||
|
@ -322,11 +322,13 @@ class TestRecursiveField:
|
||||||
|
|
||||||
# test serialization
|
# test serialization
|
||||||
serializer = self.link_serializer(value)
|
serializer = self.link_serializer(value)
|
||||||
|
|
||||||
assert serializer.data == value, \
|
assert serializer.data == value, \
|
||||||
'serialized data does not match input'
|
'serialized data does not match input'
|
||||||
|
|
||||||
# test deserialization
|
# test deserialization
|
||||||
serializer = self.link_serializer(data=value)
|
serializer = self.link_serializer(data=value)
|
||||||
|
|
||||||
assert serializer.is_valid(), \
|
assert serializer.is_valid(), \
|
||||||
'cannot validate on deserialization: %s' % dict(serializer.errors)
|
'cannot validate on deserialization: %s' % dict(serializer.errors)
|
||||||
assert serializer.validated_data == value, \
|
assert serializer.validated_data == value, \
|
||||||
|
@ -356,7 +358,6 @@ class TestRecursiveField:
|
||||||
assert serializer.validated_data == value, \
|
assert serializer.validated_data == value, \
|
||||||
'deserialized data does not match input'
|
'deserialized data does not match input'
|
||||||
|
|
||||||
|
|
||||||
# Tests for field input and output values.
|
# Tests for field input and output values.
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user