mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-06 05:20:12 +03:00
Merge branch 'recursion'
This commit is contained in:
commit
9ec631b147
|
@ -1269,6 +1269,38 @@ class HiddenField(Field):
|
|||
def to_internal_value(self, data):
|
||||
return data
|
||||
|
||||
class RecursiveField(Field):
|
||||
"""
|
||||
A field that gets its representation from its parent.
|
||||
|
||||
This method could be used to serialize a tree structure, a linked list, or
|
||||
even a directed acyclic graph. As with all recursive things, it is
|
||||
important to keep the base case in mind. In the case of the tree serializer
|
||||
example below, the base case is a node with an empty list of children. In
|
||||
the case of the list serializer below, the base case is when `next==None`.
|
||||
Above all, beware of cyclical references.
|
||||
|
||||
Examples:
|
||||
|
||||
class TreeSerializer(self):
|
||||
children = ListField(child=RecursiveField())
|
||||
|
||||
class ListSerializer(self):
|
||||
next = RecursiveField(allow_null=True)
|
||||
"""
|
||||
|
||||
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):
|
||||
"""
|
||||
|
|
|
@ -293,6 +293,35 @@ class TestCreateOnlyDefault:
|
|||
}
|
||||
|
||||
|
||||
# Tests for RecursiveField.
|
||||
# -------------------------
|
||||
class TestRecursiveField:
|
||||
def setup(self):
|
||||
class ListSerializer(serializers.Serializer):
|
||||
name = serializers.CharField()
|
||||
next = serializers.RecursiveField(allow_null=True)
|
||||
self.list_serializer = ListSerializer
|
||||
|
||||
class TreeSerializer(serializers.Serializer):
|
||||
name = serializers.CharField()
|
||||
children = serializers.ListField(child=serializers.RecursiveField())
|
||||
self.tree_serializer = TreeSerializer
|
||||
|
||||
def test_serialize_list(self):
|
||||
value = {
|
||||
'name':'first',
|
||||
'next': {
|
||||
'name':'second',
|
||||
'next':{
|
||||
'name':'third',
|
||||
'next':None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializer = self.list_serializer(value)
|
||||
assert serializer.data == value
|
||||
|
||||
# Tests for field input and output values.
|
||||
# ----------------------------------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user