1

I have the following serilizers

    class AutoSerializer(serializers.ModelSerializer):
        class Meta:
            model = Auto
            fields = ("nombre",)


    class MarcaSerializer(WritableNestedModelSerializer):
        autos = AutoSerializer(many=True)

        class Meta:
            model = Marca
            fields = ("codigo", "descripcion", "autos")

ModelViewSet

    class MarcaViewSet(viewsets.ModelViewSet):
        queryset = Marca.objects.all()
        serializer_class = MarcaSerializer

        def list(self, request, *args, **kwargs):
            queryset = self.queryset
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)

Querys

How can you optimize access to the base, that is, make fewer inquiries

1 Answer 1

2

By using a .prefetch_related(..) that fetches the related Auto instances in one fetch:

class MarcaViewSet(viewsets.ModelViewSet):
        queryset = Marca.objects.prefetch_related('autos').all()
        serializer_class = MarcaSerializer

        def list(self, request, *args, **kwargs):
            queryset = self.queryset
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)

This will first fetch the Marca objects, and then look with a JOIN for all the Auto objects that are related, and fetch all these objects with a single fetch into memory as well.

So the Auto objects are loaded in bulk instead of lazily each time fetch the Autos for a specific Marca object.

This kind of optization is documented in the article mentioned by @Jerin Peter George: "Optimizing slow Django REST Framework performance".

This article also discusses how to specify such prefetches at the side of the serializer, such that in case other tasks are done, the prefetch is not done. So we could for example write:

class AutoSerializer(serializers.ModelSerializer):

    class Meta:
        model = Auto
        fields = ("nombre",)


class MarcaSerializer(WritableNestedModelSerializer):
    autos = AutoSerializer(many=True)

    @classmethod
    def setup_eager_loading(cls, queryset):
        return queryset.prefetch_related('autos')

    class Meta:
        model = Marca
        fields = ("codigo", "descripcion", "autos")

and then write:

class MarcaViewSet(viewsets.ModelViewSet):
    queryset = Marca.objects.all()
    serializer_class = MarcaSerializer

    def list(self, request, *args, **kwargs):
        serializer = self.get_serializer
        queryset = serializer.setup_eager_loading(self.queryset)
        serializer = serializer(queryset, many=True)
        return Response(serializer.data)
Sign up to request clarification or add additional context in comments.

2 Comments

One of the best article I've read about Django Query Optimization
@JerinPeterGeorge: thanks. I added a link to the article in the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.