This solution is almost similar with the other solutions posted here but has a slight difference in terms of child repetition problem at the root level( if you think its as a problem). For an example
class RecursiveSerializer(serializers.Serializer):
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
class CategoryListSerializer(ModelSerializer):
sub_category = RecursiveSerializer(many=True, read_only=True)
class Meta:
model = Category
fields = (
'name',
'slug',
'parent',
'sub_category'
)
and if you have this view
class CategoryListAPIView(ListAPIView):
queryset = Category.objects.all()
serializer_class = CategoryListSerializer
This will produce the following result,
[
{
"name": "parent category",
"slug": "parent-category",
"parent": null,
"sub_category": [
{
"name": "child category",
"slug": "child-category",
"parent": 20,
"sub_category": []
}
]
},
{
"name": "child category",
"slug": "child-category",
"parent": 20,
"sub_category": []
}
]
Here the parent category
has a child category
and the json representation is exactly what we want it to be represent.
but you can see there is a repetition of the child category
at the root level.
As some people are asking in the comment sections of the above posted answers that how can we stop this child repetition at the root level, just filter your queryset with parent=None
, like as the following
class CategoryListAPIView(ListAPIView):
queryset = Category.objects.filter(parent=None)
serializer_class = CategoryListSerializer
it will solve the problem.
NOTE: This answer might not directly related with the question, but the problem is somehow related. Also this approach of using RecursiveSerializer
is expensive. Better if you use other options which is performance prone.