Serializers Prefetch in View

In Django / DRF, we can provide Prefetch, but is it the role of the serializer to have "good" datas. For example I have this basic code:

from rest_framework import generics, serializers
from app.models import Client


class ClientListCreate(generics.ListCreateAPIView):
    queryset = Client.objects.all()
    serializer = ClientSerializer()

class ClientSerializer(serializers.ModelSerializer):
    amount_users = serializers.SerializerMethodField()
    
    def get_amount_users(self, obj: Client):
        return obj.users.filter(is_active=True).count() # N+1 Queries

This is something to prevent N+1 queries (but the serializer is not stand-alone) :

from rest_framework import generics, serializers
from app.models import Client


class ClientListCreate(generics.ListCreateAPIView):
    queryset = Client.objects.all().prefetch_related(
        Prefetch(
            "users",
            queryset=User.objects.filter(is_active=True)
        )
    )
    serializer = ClientSerializer()

class ClientSerializer(serializers.ModelSerializer):
    amount_users = serializers.SerializerMethodField()
    
    def get_amount_users(self, obj: Client):
        return obj.users.count()

This is something to prevent N+1 queries and be standalone :

from rest_framework import generics, serializers

class PrefetchedDataMixin:
    def has_prefetch(self, to_attr: str = "", related_name: str = ""):
        ...

    def get_prefetch(self, fct, to_attr: str = "", related_name: str = ""):
        ...

class Client(models.Model, PrefetchedDataMixin):
    ...


class ClientListCreate(generics.ListCreateAPIView):
    queryset = Client.objects.all().prefetch_related(
        Prefetch(
            "users",
            queryset=User.objects.filter(is_active=True),
            to_attr="active_users"
        )
    )
    serializer = ClientSerializer()

class ClientSerializer(serializers.ModelSerializer):
    amount_users = serializers.SerializerMethodField()
    
    def get_amount_users(self, obj: Client):
        users = obj.get_prefetch(
            lambda client: client.users.filter(is_active=True),
            to_attr="active_users",
        )
        return users.count()

What would be the best practice for a large scallable app ?

Does it just depend on the company practices ?

Вернуться на верх