Ускорение работы 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']
Вернуться на верх