How can I optimize queries django rest-framework

北城余情 提交于 2019-12-11 08:55:48

问题


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:


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)


来源:https://stackoverflow.com/questions/50950044/how-can-i-optimize-queries-django-rest-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!