Ускорение работы Django Rest Framework Model Serializer N+1 Query problem
У меня есть класс DRF ModelSerializer
, который сериализует модельOrder
. У этого сериализатора есть поле:
num_modelA = serializers.SerializerMethodField()
`
def get_num_modelA(self, o):
r = ModelA.objects.filter(modelB__modelC__order=o).count()
return r
Где модельА имеет поле ForeignKey
modelB
, модельВ имеет поле ForeignKey
modelC
, а модельС имеет поле ForeignKey
order
.
Проблема в том, что для каждого заказа, который сериализуется, делается дополнительный запрос к БД, что снижает производительность.
Я реализовал статический метод setup_eager_loading
как описано здесь, который устранил проблему 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 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']