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 ?