Search code examples
pythondjangodjango-rest-framework

Overriding DRF ListAPIView list() method


I have a DRF Project, which has a ListAPIView for a model called Category. This model, has a ForeginKey to itself named parent_category and with related name of subcategories. I want my URLs to behave like this:

  1. get a list of Categories with no parent: example.com/api/categories
  2. get a list of subcategories of an object with some id: example.com/api/categories/{id_here}

models.py:

class Category(models.Model):
    name = models.CharField(max_length=100)
    parent_category = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE,
                                        related_name='subcategories')

views.py:

class CategoryList(generics.ListAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

And I have no idea how to write my urls.py. Do I need DRF routers? or Django path works fine? I don't know which to choose or how to use them for this project. I thought if I override ListAPIMixin's list() method, it would work, but I don't even know what to write in that.


Solution

  • I made a dummy project for myself and implemented it like this

    You can do this by rewriting get_queryset

    example code

    views

    from .models import Category
    from rest_framework.generics import ListAPIView
    from .serializers import CategorySerializer
    
    
    class CategoryViewSet(ListAPIView):
        serializer_class = CategorySerializer
        def get_queryset(self):    
            parent_category = self.kwargs.get("parent_category") or None
            return Category.objects.filter(parent_category=parent_category)
    

    urls

    you can set multiple-routes option

    from django.contrib import admin
    from django.urls import path
    from cate.views import CategoryViewSet
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', CategoryViewSet.as_view() ,name="category"),
        path('<int:parent_category>/', CategoryViewSet.as_view() ,name="category"),
        
    ]
    

    Serializers

    from .models import Category
    from rest_framework import serializers
    
    
    class CategorySerializer(serializers.ModelSerializer):
        class Meta:
            model = Category
            fields = "__all__"
    

    also see DRF-Filtering Maybe it will be useful for you