Merge branch 'recursion'

This commit is contained in:
Warren Jin 2015-01-25 23:11:30 -05:00
commit 9969dc0e68
2 changed files with 16 additions and 9 deletions

View File

@ -1269,6 +1269,7 @@ class HiddenField(Field):
def to_internal_value(self, data): def to_internal_value(self, data):
return data return data
class RecursiveField(Field): class RecursiveField(Field):
""" """
A field that gets its representation from its parent. A field that gets its representation from its parent.
@ -1281,27 +1282,33 @@ class RecursiveField(Field):
Above all, beware of cyclical references. Above all, beware of cyclical references.
Examples: Examples:
class TreeSerializer(self): class TreeSerializer(self):
children = ListField(child=RecursiveField()) children = ListField(child=RecursiveField())
class ListSerializer(self): class ListSerializer(self):
next = RecursiveField(allow_null=True) next = RecursiveField()
""" """
def __init__(self, *args, **kwargs):
kwargz = {'required': False}
kwargz.update(kwargs)
super(RecursiveField, self).__init__(*args, **kwargz)
def _get_parent(self): def _get_parent(self):
if hasattr(self.parent, 'child') and self.parent.child is self: if hasattr(self.parent, 'child') and self.parent.child is self:
# Recursive field nested inside of some kind of composite list field # Recursive field nested inside of some kind of composite list field
return self.parent.parent return self.parent.parent
else: else:
return self.parent return self.parent
def to_representation(self, value): def to_representation(self, value):
return self._get_parent().to_representation(value) return self._get_parent().to_representation(value)
def to_internal_value(self, data): def to_internal_value(self, data):
return self._get_parent().to_internal_value(data) return self._get_parent().to_internal_value(data)
class SerializerMethodField(Field): class SerializerMethodField(Field):
""" """
A read-only field that get its representation from calling a method on the A read-only field that get its representation from calling a method on the

View File

@ -313,7 +313,7 @@ class TestRecursiveField:
'name': 'first', 'name': 'first',
'next': { 'next': {
'name': 'second', 'name': 'second',
'next':{ 'next': {
'name': 'third', 'name': 'third',
'next': None, 'next': None,
} }
@ -328,17 +328,17 @@ class TestRecursiveField:
# 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' 'cannot validate on deserialization: %s' % dict(serializer.errors)
assert serializer.validated_data == value, \ assert serializer.validated_data == value, \
'deserialized data does not match input' 'deserialized data does not match input'
def test_node_serializer(self): def test_node_serializer(self):
value = { value = {
'name': 'root', 'name': 'root',
'children': [{ 'children': [{
'name': 'first child', 'name': 'first child',
'children': [], 'children': [],
},{ }, {
'name': 'second child', 'name': 'second child',
'children': [], 'children': [],
}] }]
@ -350,9 +350,9 @@ class TestRecursiveField:
'serialized data does not match input' 'serialized data does not match input'
# deserialization # deserialization
serializer = self.link_serializer(data=value) serializer = self.node_serializer(data=value)
assert serializer.is_valid(), \ assert serializer.is_valid(), \
'cannot validate on deserialization' 'cannot validate on deserialization: %s' % dict(serializer.errors)
assert serializer.validated_data == value, \ assert serializer.validated_data == value, \
'deserialized data does not match input' 'deserialized data does not match input'