Как оптимизировать N+1 SQL-запросов при сериализации поста с комментариями mptt?

У меня есть следующий сериализатор для подробного сообщения:

class ArticleDetailSerializer(serializers.ModelSerializer):
    author = ArticleAuthorSerializer(read_only=True)
    comments = CommentSerializer(many=True, read_only=True)

    class Meta:
        model = Article
        fields = '__all__'

Сериализатор комментариев:

class CommentSerializer(serializers.ModelSerializer):

    class Meta:
        model = Comment
        fields = '__all__'

    def get_fields(self):
        fields = super(CommentSerializer, self).get_fields()
        fields['children'] = CommentSerializer(many=True, required=False, source='get_children')
        return fields

При работе со списком комментариев я получаю 2 sql-запроса, если работаю с get_cached_trees()

class CommentListAPIView(generics.ListAPIView):
    serializer_class = serializers.CommentSerializer
    queryset = Comment.objects.all().get_cached_trees()

Но как заставить работать то же самое для статьи со списком комментариев?

class ArticleDetailAPIView(generics.RetrieveAPIView):
    serializer_class = serializers.ArticleDetailSerializer
    queryset = Article.custom.all()
    lookup_field = 'slug'

    def get_queryset(self):
        queryset = self.queryset.prefetch_related(Prefetch('comments', queryset=Comment.objects.all().get_cached_trees()))
        return queryset

Я использовал prefetch_related(), но это не сработало. Я использовал Prefetch(), он выдал мне ошибку:

'list' object has no attribute '_add_hints'

Похоже, я потерял возможность оптимизировать комментарии mptt для статьи. Но если использовать те же комментарии, рендеринг согласно документации в шаблоне Django, то такой проблемы не наблюдается. Прошу вашей помощи, уважаемые программисты и эксперты.

Подобное решение сработало для меня.

class ArticleDetailSerializer(serializers.ModelSerializer):
    author = ArticleAuthorSerializer(read_only=True)
    comments = serializers.SerializerMethodField()

    class Meta:
        model = Article
        fields = '__all__'

    def get_comments(self, obj):
        qs = obj.comments.all().get_cached_trees()
        return CommentSerializer(qs, many=True).data

В результате все запросы сократились с 11 SQL до 4.

Вернуться на верх