alternative approach that allows for validation

This commit is contained in:
Warren Jin 2015-01-27 22:15:08 -05:00
parent c6d44789e2
commit 09aff6daeb
2 changed files with 36 additions and 15 deletions

View File

@ -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):
""" """

View File

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