Как оптимизировать 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.