Совокупные итоги набора представлений приводят к Django Rest Framework

#django #django-rest-framework

#django #django-rest-framework

Вопрос:

У меня есть ViewSet, который выводит набор результатов:

 {
    "count": 19355,
    "next": null,
    "previous": null,
    "results": [
        {
            "duration": 5,
            ...
        },
        {
            "duration": 5,
            ...
        },
        ...
    ]
}
  

Я хотел бы объединить итоги продолжительности результатов прямо в этой удобной маленькой верхней области рядом с «count». Я знаю, как это сделать в наборе запросов, используя аннотацию и сумму, но я не вижу способа получить это в выводе набора представлений.

Желаемый результат для этого набора данных будет:

 {
    "count": 19355,
    "total_duration": 10,
    "next": null,
    "previous": null,
    "results": [
        {
            "duration": 5,
            ...
        },
        {
            "duration": 5,
            ...
        },
        ...
    ]
}
  

Я ценю помощь!

Комментарии:

1. Глядя на выходные данные набора представлений, вы используете разбивку на страницы, не так ли? Вы хотите total_duration быть суммой длительностей страницы или всего набора запросов?

2. Да, и я хотел бы, чтобы это было общее количество всего набора запросов. Что, я полагаю, может потребовать другого запроса к БД, и это нормально. Я бы просто предпочел не создавать совершенно новую конечную точку только для агрегатов.

Ответ №1:

Я бы предложил реализовать это с помощью выделенного класса разбивки на страницы.

 class PaginationWithAggregates(pagination.LimitOffsetPagination):
    def paginate_queryset(self, queryset, request, view=None):
        self.total_duration = queryset.aggregate(total_duration=Sum('duration'))['total_duration']
        return super(PaginationWithAggregates, self).paginate_queryset(queryset, request, view)

    def get_paginated_response(self, data):
        paginated_response = super(PaginationWithAggregates, self).get_paginated_response(data)
        paginated_response.data['total_duration'] = self.total_duration
        return paginated_response
  

Не забудьте объявить этот класс разбивки на страницы в вашем GenericView.

Комментарии:

1. Гениально! Никогда не думал помещать это в класс разбивки на страницы. Сработало как шарм (пришлось внести некоторые изменения в ваше решение, чтобы переместить total_duration в полезную нагрузку данных, а не в заголовок ответа.) Спасибо!

2. Удивительно! Это работает полностью, сэкономило мне часы. Спасибо @Michael. 🙂