我如何优化查询Django Rest框架

时间:2018-06-20 13:59:09

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

我有以下Serilizers

{'products': product.template(10, 35, 36, 34, 6, 3, 24, 28, 5, 26, 18, 4, 1, 2, 8, 37, 25, 16, 17, 14, 20, 11, 21, 31, 12, 9, 32, 29, 30, 27, 23, 13, 15, 33, 7, 19, 22, 38), 'categ_value': {'Physique': {'categ_name': 'Physique', 'valuation': 760512.0}, 'En vente': {'categ_name': 'En vente', 'valuation': 0.0}, 'Logiciel': {'categ_name': 'Logiciel', 'valuation': 0.0}, 'Services': {'categ_name': 'Services', 'valuation': 0.0}, 'Tous': {'categ_name': 'Tous', 'valuation': 0.0}}}

ModelViewSet

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

Querys

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

1 个答案:

答案 0 :(得分:2)

通过使用.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对象,并用 single < / em>也提取到内存中。

因此,将Auto对象加载到批量中,而不是每次为特定的 Auto每次获取Marca时都懒惰加载对象。

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