加速 Django Rest Framework 模型序列化器 N+1 查询问题

问题描述 投票:0回答:1

我有一个 DRF

ModelSerializer
类,用于序列化
Order
模型。这个序列化器有一个字段:

num_modelA = serializers.SerializerMethodField()
`

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

    return r

其中 ModelA 有一个

ForeignKey
字段
modelB
,ModelB 有一个
ForeignKey
字段
modelC
,ModelC 有一个
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 由多个外键分隔。让我知道是否还有其他有用的信息

django api serialization django-rest-framework django-serializer
1个回答
1
投票

您可以使用注释:

from django.db.models import Count

# …

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

Order
的序列化器中,您可以使用
num_modelA
作为
IntegerField
:

from rest_framework import serializers

class OrderSerializer(serializers.ModelSerializer):
    num_modelA = serializers.IntegerField()

    class Meta:
        model = Order
        fields = ['num_modelA', 'and', 'other', 'fields']
© www.soinside.com 2019 - 2024. All rights reserved.