加速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']
我有一个 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']