How to display all child category from parent category in django-rest-framework

Viewed 47

I'm trying to show my all children category from parent category. I want to just hit one API end and show all tables which is related to that item. I want to hit "Master-Category" and show all releated "Category","Sub-Category" and "Root-Item" in Hierarchy form. I display all the data but cannot in Hierarchy form.
Can anyone please give me the solution for this problem.
Model.py

from django.db import models
from django.contrib.auth.models import User

class MasterCategory(models.Model):
  user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, 
  verbose_name="Created By")
  title = models.CharField(max_length=100, null=False, blank=False)
  description = models.TextField(default='')

  def __str__(self):
    return str(self.title)

  @property
  def category(self):
    data = NewCategory.objects.filter(master_category__id=self.id).values
  return data

  @property
  def sub_category(self):
    data = NewSubcategory.objects.filter(category__id=self.id).values
  return data

  @property
  def root_item(self):
    data = Rootitem.objects.filter(sub_category__id=self.id).values
  return data


class NewCategory(models.Model):
  user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, 
   verbose_name="Created By")
  title = models.CharField(max_length=100, null=False, blank=False)
  description = models.TextField(default="")
  master_category = models.ForeignKey(
    MasterCategory, on_delete=models.CASCADE, null=True, blank=True)

  def __str__(self):
    return str(self.title)


class NewSubcategory(models.Model):
  user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, 
         verbose_name="Created By")
  title = models.CharField(max_length=100, null=False, blank=False)
  description = models.TextField(default="")
  category = models.ForeignKey(NewCategory, on_delete=models.CASCADE, null=True, 
             blank=True)

  def __str__(self):
    return str(self.title)

class Rootitem(models.Model):
  user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, 
         verbose_name="Created By")
  title = models.CharField(max_length=100, null=False, blank=False)
  description = models.TextField(default="")
  sub_category = models.ForeignKey(NewSubcategory, on_delete=models.CASCADE, 
                 null=True, blank=True)

  def __str__(self):
    return str(self.title)

Serializers.py
I add @property function name in MasterCategorySerializer fields, "category", "sub_category", "root_item"

    from .models import MasterCategory, NewCategory, NewSubcategory, Rootitem
    from rest_framework import serializers

    class MasterCategorySerializer(serializers.ModelSerializer):
      class Meta:
        model = MasterCategory
        fields = ["title", 'category', 'sub_category', 'root_item']


    class NewCategorySerializer(serializers.ModelSerializer):
      class Meta:
        model = NewCategory
        fields = "__all__"



    class NewSubcategorySerializer(serializers.ModelSerializer):
      new_cat = NewCategorySerializer(source='category',read_only=True, many=True)
     class Meta:
        model = NewSubcategory
        fields = "__all__"



    class RootitemSerializer(serializers.ModelSerializer):
      class Meta:
        model = Rootitem
        fields = "__all__"

**Viewset.py**

from API_app.models import MasterCategory
from API_app.serializers import MasterCategorySerializer
from rest_framework import viewsets

class MasterCategoryViewSet(viewsets.ModelViewSet):

  queryset = MasterCategory.objects.all()
  serializer_class = MasterCategorySerializer

My Desired Output, what i want.

    {
      Electronics <---- Master-Category
                 {
                   Smart-Phone  <---- Category
                               {
                                 Samsung  <---- Sub-Category
                                        {
                                         Samsung S20 Ultra  <---- Root-Item
                                         }
                                }
                   }
    
    }

1 Answers

Change your serializers as below. For this nested structure you don't need properties. As tables are connected with foreign key you can define related name between models and assign to its serializer. Default related name between table is tablename_set.

class RootitemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Rootitem
        fields = "__all__"


class NewSubcategorySerializer(serializers.ModelSerializer):
    rootitem_set = RootitemSerializer(many=True)

    class Meta:
        model = NewSubcategory
        fields = "__all__"


class NewCategorySerializer(serializers.ModelSerializer):
    newsubcategory_set = NewSubcategorySerializer(many=True)
    
    class Meta:
        model = NewCategory
        fields = "__all__"


class MasterCategorySerializer(serializers.ModelSerializer):
    newcategory_set = NewCategorySerializer(many=True)
    class Meta:
        model = MasterCategory
        fields = "__all__"

We have relationship between MasterCategory and NewCategory. As you don't define related_name therefore related name is newcategory_set and its response is NewCategorySeralizer. Make many=True because they are related with foreign key as there can be multiple newcategory related to mastercategory. Other relations are same as above explanation.

If you want to change this default related name then look at related_name, you can define it inside models.ForeignKey()

Related