diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 7c08ad4a9..fc5db78cc 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1269,6 +1269,7 @@ class HiddenField(Field): def to_internal_value(self, data): return data + class RecursiveField(Field): """ A field that gets its representation from its parent. @@ -1281,27 +1282,33 @@ class RecursiveField(Field): Above all, beware of cyclical references. Examples: - + class TreeSerializer(self): children = ListField(child=RecursiveField()) 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): if hasattr(self.parent, 'child') and self.parent.child is self: # Recursive field nested inside of some kind of composite list field return self.parent.parent else: return self.parent - + def to_representation(self, value): return self._get_parent().to_representation(value) def to_internal_value(self, data): return self._get_parent().to_internal_value(data) + class SerializerMethodField(Field): """ A read-only field that get its representation from calling a method on the diff --git a/tests/test_fields.py b/tests/test_fields.py index e87c57088..a832b75f0 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -313,7 +313,7 @@ class TestRecursiveField: 'name': 'first', 'next': { 'name': 'second', - 'next':{ + 'next': { 'name': 'third', 'next': None, } @@ -328,17 +328,17 @@ class TestRecursiveField: # test deserialization serializer = self.link_serializer(data=value) assert serializer.is_valid(), \ - 'cannot validate on deserialization' + 'cannot validate on deserialization: %s' % dict(serializer.errors) assert serializer.validated_data == value, \ 'deserialized data does not match input' def test_node_serializer(self): value = { - 'name': 'root', + 'name': 'root', 'children': [{ 'name': 'first child', 'children': [], - },{ + }, { 'name': 'second child', 'children': [], }] @@ -350,9 +350,9 @@ class TestRecursiveField: 'serialized data does not match input' # deserialization - serializer = self.link_serializer(data=value) + serializer = self.node_serializer(data=value) assert serializer.is_valid(), \ - 'cannot validate on deserialization' + 'cannot validate on deserialization: %s' % dict(serializer.errors) assert serializer.validated_data == value, \ 'deserialized data does not match input'