TIL

ListSerializerMixin

I often want to include related nested objects in my Django REST Framework ModelViewSets for CRUD operations, but don’t want those related objects cluttering up the list view. To accomplish this, you can return a serializer from get_serializer_class() that doesn’t include the nested relation when the ViewSet action is list. I ended up doing this on a bunch of viewsets, so I factored the logic out into a separate mixin:

from typing import Union
from rest_framework import viewsets

class ListSerializerMixin(object):  
    list_serializer_class = None  
  
    def get_serializer_class(  
        self: Union[viewsets.GenericViewSet, "ListSerializerMixin"]  
    ):  
        if self.list_serializer_class and self.action == "list":  
            return self.list_serializer_class  
        return super(viewsets.GenericViewSet, self).get_serializer_class()

On your viewset, you can inherit from ListSerializerMixinMake sure to add the mixin before the ViewSet in your superclass list. then add the list_serializer_class attribute next to serializer_class instead of overriding the method directly:

class ObjectViewSet(ListSerializerMixin, viewsets.ModelViewSet):  
    serializer_class = ObjectDetailSerializer  
    list_serializer_class = ObjectListSerializer  
    permission_classes = [IsAuthenticated]  
  
    def get_queryset(self):  
        return Object.objects.all().prefetch_related("related_items")

This leads to serializers that are easier to read at-a-glance, and slightly easier to write.