Це рішення майже схоже на інші рішення, опубліковані тут, але має невелику різницю щодо проблеми повторення дітей на кореневому рівні (якщо ви вважаєте це проблемою). Для прикладу
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'
)
і якщо у вас такий погляд
class CategoryListAPIView(ListAPIView):
queryset = Category.objects.all()
serializer_class = CategoryListSerializer
Це дасть такий результат,
[
{
"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": []
}
]
Тут представлення parent category
has child category
і json - саме те, що ми хочемо, щоб воно було представлене.
але ви можете бачити, що є повторення child category
на кореневому рівні.
Оскільки деякі люди запитують у розділах коментарів до опублікованих вище відповідей, що як ми можемо зупинити повторення цієї дочірньої групи на кореневому рівні , просто відфільтруйте набір запитів за допомогою parent=None
, як показано нижче
class CategoryListAPIView(ListAPIView):
queryset = Category.objects.filter(parent=None)
serializer_class = CategoryListSerializer
це вирішить проблему.
ПРИМІТКА: Ця відповідь може не мати прямого відношення до запитання, але проблема якось пов’язана. Також такий підхід використання RecursiveSerializer
є дорогим. Краще, якщо ви використовуєте інші варіанти, які схильні до ефективності.