I'm using DRF. How can I get hierarchical JSON by django ORM? what the query should look like?
CategoryModel.objects.filter(active=True).select_related() or prefetch_related()?
I have model that looks like this:
class Category(models.Model):
parent = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True)
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True, default='', blank=True)
active = models.BooleanField(default=True)
serializers:
class ParentCategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class CategoryListSerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['name', 'slug', 'parent']
parent = ParentCategorySerializer(many=True)
I want to get something like this (greater depth possible):
{
"name": "First category",
"slug": "first-category",
"subcategories": [
{
"name": "First subcategory one",
"slug": "first-subcategory-one",
"subcategories": null
},
{
"name": "First subcategory two",
"slug": "first-subcategory-two",
"subcategories": null
},
]
},
{
"name": "Second category",
"slug": "second-category",
"subcategories": []
}
CodePudding user response:
views.py
:
from rest_framework.viewsets import ModelViewSet
from .models import Category
from .serializers import CategorySerializer
class CategoryViewSet(ModelViewSet):
queryset = Category.objects.filter(parent=None)
serializer_class = CategorySerializer
serialisers.py
:
from rest_framework import serializers
from .models import Category
from django.db.models import CharField, Value
class CategorySerializer(serializers.ModelSerializer):
subcategories = serializers.SerializerMethodField()
def get_subcategories(self, obj):
return (
Category.objects.filter(parent_id__isnull=False, parent_id=obj.id)
.annotate(subcategories=Value(None, output_field=CharField()))
.values("name", "slug", "subcategories")
)
class Meta:
model = Category
fields = ["name", "slug", "subcategories"]
urls.py
:
from django.urls import path
from . import views
urlpatterns = [
path("category/", views.CategoryViewSet.as_view({"get": "list"})),
]