【问题标题】:How can I optimize queries django rest-framework如何优化查询 django rest-framework
【发布时间】:2023-03-30 12:05:02
【问题描述】:

我有以下序列化程序

    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")

模型视图集

    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

如何优化对基地的访问,即减少查询次数

【问题讨论】:

    标签: django django-rest-framework django-queryset


    【解决方案1】:

    通过使用.prefetch_related(..) 一次获取相关的Auto 实例:

    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)

    这将首先获取Marca 对象,然后使用JOIN 查找所有相关的Auto 对象,并通过单个 获取所有这些对象到内存中也是。

    因此Auto 对象被批量 加载,而不是每次为特定 Marca 对象获取Autos 时都懒惰地加载。

    这种优化记录在@Jerin Peter George 提到的文章中:"Optimizing slow Django REST Framework performance"

    本文还讨论了如何在 serializer 一侧指定此类预取,以便在完成其他任务的情况下,预取完成。所以我们可以例如写:

    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")

    然后写:

    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)

    【讨论】:

    • 我读过的关于Django Query Optimization的最好的文章之一
    • @JerinPeterGeorge:谢谢。我在答案中添加了文章的链接。
    猜你喜欢
    • 2018-10-23
    • 2019-08-15
    • 2020-11-27
    • 2014-04-16
    • 2021-08-24
    • 1970-01-01
    • 2022-11-13
    • 2011-10-08
    • 2012-03-19
    相关资源
    最近更新 更多