Получение полей из дополнительных методов менеджера с помощью django-rest-framework

У меня есть следующий пользовательский менеджер моделей в Django, который предназначен для подсчета количества связанных комментариев и добавления их в набор запросов объектов:

class PublicationManager(models.Manager):
    def with_counts(self):
        return self.annotate(
            count_comments=Coalesce(models.Count('comment'), 0)
        )

Добавление этого менеджера в модель не добавляет автоматически дополнительное поле в DRF. В своем представлении API я нашел способ получить поле count_comments, переопределив функцию get следующим образом:

class PublicationDetails(generics.RetrieveUpdateAPIView):
    queryset = Publication.objects.with_counts()
    ...

    def get(self, request, pk):
        queryset = self.get_queryset()
        serializer = self.serializer_class(queryset.get(id=pk))
        
        data = {**serializer.data}
        data['count_comments'] = queryset.get(id=pk).count_comments
        return Response(data)

Это работает для одного экземпляра, но когда я пытаюсь применить это к постраничному представлению списка с помощью pagination_class, переопределение метода get, похоже, удаляет функциональность постраничного представления (т.е. я получаю список результатов вместо обычного объекта страницы с предыдущим, следующим и т.д.). Это наводит меня на мысль, что я делаю что-то не так: должен ли я вместо этого добавить дополнительное поле пользовательского менеджера в сериализатор? Я не уверен, как действовать дальше, учитывая, что я использую сериализатор модели. Должен ли я использовать базовый сериализатор?

В итоге я решил эту проблему, создав пользовательский класс пагинации и переопределив метод get_paginated_response.

class PaginationPublication(pagination.PageNumberPagination):
    def get_paginated_response(self, data):
        for item in data:
            publication = Publication.objects.with_counts().get(id=item['id'])
            item['count_comments'] = publication.count_comments

        return super().get_paginated_response(data)

Не уверен, что это самое эффективное решение, но оно работает!

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