Home > Back-end >  Django rest framework self nesteg query
Django rest framework self nesteg query

Time:09-09

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"})),
]
  • Related