From 9c95d15cf24d19510fc5c074e9ddbfaeb557d77e Mon Sep 17 00:00:00 2001 From: lukasbuenger Date: Tue, 2 Apr 2013 19:27:06 +0200 Subject: [PATCH] Introducing max_depth argument --- docs/api-guide/relations.md | 6 ++++ rest_framework/relations.py | 9 +++++- rest_framework/tests/relations_recursive.py | 34 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 05b081e22..ca7b58132 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -419,6 +419,12 @@ You could have the child objects nested recursively with the following serialize model = TreeModel exclude = ('id', ) +By default, the number of recursions is made until no further objects are found (`max_depth=-1`). + +However, you can restrict the number of recursions by passing the number of levels as `max_depth` argument: + + children = RecursiveRelatedField(many=True, max_depth=1) + Note that as for now the the `RecursiveRelatedField` is read only. --- diff --git a/rest_framework/relations.py b/rest_framework/relations.py index f982ad217..dc90c84cc 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -482,9 +482,10 @@ class HyperlinkedIdentityField(Field): class RecursiveRelatedField(RelatedField): - def __init__(self, *args, **kwargs): + def __init__(self, max_depth=-1, *args, **kwargs): super(RecursiveRelatedField, self).__init__(*args, **kwargs) # Forced read only. + self.max_depth = max_depth self.read_only = True def field_to_native(self, obj, field_name): @@ -493,6 +494,12 @@ class RecursiveRelatedField(RelatedField): serializer = serializer_class() serializer.initialize(self.parent, field_name) + if self.max_depth > -1: + if self.max_depth > 0: + serializer.fields[field_name].max_depth = self.max_depth - 1 + else: + return [] if self.many else None + if self.many: related_manager = getattr(obj, self.source or field_name) if not obj.__class__ == related_manager.model: diff --git a/rest_framework/tests/relations_recursive.py b/rest_framework/tests/relations_recursive.py index 4e7854327..fc21c3f08 100644 --- a/rest_framework/tests/relations_recursive.py +++ b/rest_framework/tests/relations_recursive.py @@ -23,6 +23,15 @@ class TreeSerializer(serializers.ModelSerializer): exclude = ('id', ) +class MaxDepthTreeSerializer(serializers.ModelSerializer): + + children = RecursiveRelatedField(many=True, max_depth=1) + + class Meta: + model = TreeModel + exclude = ('id', ) + + class ChainModel(models.Model): name = models.CharField(max_length=127) @@ -115,3 +124,28 @@ class TestRecursiveRelatedField(TestCase): } self.assertEqual(serializer.data, expected) + def test_max_depth(self): + serializer = MaxDepthTreeSerializer(self.tree_root) + expected = { + 'children': [ + { + 'children': [], + 'name': 'Child 1:0', + 'parent': 1 + }, + { + 'children': [], + 'name': 'Child 1:1', + 'parent': 1 + }, + { + 'children': [], + 'name': 'Child 1:2', + 'parent': 1 + } + ], + 'name': 'Tree Root', + 'parent': None + } + self.assertEqual(serializer.data, expected) +