加速Django Rest Framework Model Serializer N+1 Query问题

Speeding up Django Rest Framework Model Serializer N+1 Query problem

我有一个 DRF ModelSerializer class 可以序列化一个 Order 模型。这个序列化器有一个字段:

num_modelA = serializers.SerializerMethodField() `

def get_num_modelA(self, o):
    r = ModelA.objects.filter(modelB__modelC__order=o).count()

    return r

模型 A 有一个 ForeignKey 字段 modelB,模型 B 有一个 ForeignKey 字段 modelC,模型 C 有一个 ForeignKey 字段 order.

这个问题显然是,对于每个序列化的订单,它都会对数据库进行额外的查询,从而降低性能。

我已经实施了一个静态方法 setup_eager_loading,如 here 所述,它解决了我所拥有的其他字段的 N+1 查询问题。

@staticmethod
def setup_eager_loading(queryset):
    # select_related for "to-one" relationships
    queryset = queryset.select_related('modelD','modelE')
    
    return queryset

我的想法是我也可以使用 prefetch_related 来减少查询的数量。但我不确定如何执行此操作,因为 Order 和 ModelA 由多个外键分隔。让我知道是否有任何其他信息有用

您可以使用注释:

from django.db.models import <strong>Count</strong>

# …

@staticmethod
def setup_eager_loading(queryset):
    # select_related for "to-one" relationships
    return queryset.select_related('modelD','modelE').annotate(
        <strong>num_modelA=Count('modelC__modelB__modelA')</strong>
    )

Order 的序列化程序中,您可以将 num_modelA 用作 IntegerField:

from rest_framework import serializers

class OrderSerializer(serializers.ModelSerializer):
    num_modelA = serializers.<strong>IntegerField()</strong>

    class Meta:
        model = Order
        fields = [<strong>'num_modelA'</strong>, 'and', 'other', 'fields']