Django Rest Framework: добавить значение в ListAPIView

#django #django-rest-framework #django-views #drf-queryset

#django #django-rest-framework #django-представления #drf-набор запросов

Вопрос:

Сообщество StackOverflow,

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

serializers.py

 class PricetrendSerializer(serializers.ModelSerializer):
timestamp = serializers.DateTimeField()
average_price = serializers.IntegerField()

class Meta:
    model = Cars
    fields = ('timestamp', 'average_price')
 

views.py

 class Pricetrend(generics.ListAPIView):
queryset = Cars.objects.annotate(timestamp=TruncMonth('timestamp')).values('timestamp').annotate(average_price=Avg('price'))
serializer_class = PricetrendSerializer
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
filterset_class = PriceFilter
search_fields = ['description']
ordering_fields = ['timestamp', 'average_price']
ordering = ['timestamp']
permission_classes = (permissions.IsAuthenticated,)
 

Что дает мне следующий результат:

     {
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "timestamp": "2020-04-01T00:00:00",
      "average_price": 90274
    },
    {
      "timestamp": "2020-05-01T00:00:00",
      "average_price": 99253
    }
    ]
    }   
 

Я хотел бы также объединить общую среднюю цену и добавить ее в выходные данные, например:

     {
  "count": 2,
  "next": null,
  "previous": null,
  "total_average_price": 125000,
  "results": [
    {
      "timestamp": "2020-04-01T00:00:00",
      "average_price": 90274
    },
    {
      "timestamp": "2020-05-01T00:00:00",
      "average_price": 99253
    }
    ]
    }   
 

К сожалению, я не знаю, как это можно было бы сделать, поскольку добавление его в сериализатор приведет к получению total_average_price в каждом объекте JSON. Я также пытался переопределить ListAPIView (получить функцию), но это убило встроенную разбивку на страницы: (

Я надеюсь, что кто-нибудь сможет помочь мне найти аккуратный способ решить эту проблему.

Ответ №1:

Вы можете создать пользовательский класс разбивки на страницы и переопределить его get_paginated_response . В paginations.py:

 class PricesPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page'

    def get_paginated_response(self, data):
        prices = [dict(item)['average_price'] for item in data]
        page_price_avg = sum(prices)/ len(prices)
        return Response({
            'next': self.get_next_link(),
            'previous': self.get_previous_link(),
            'count': self.page.paginator.count,
            'page_price_avg': page_price_avg,
            'results': data,
        })
 

В views.py , установите свою пользовательскую разбивку на страницы:

 class PriceTrendListView(ListAPIView):
    pagination_class = PricesPagination
    serializer_class = PriceTrendSerializer
    queryset = Car.objects.all()
 

Затем вы сможете увидеть среднюю цену для каждой страницы.

Ответ №2:

 from rest_framework import pagination
from rest_framework.response import Response


class CustomPagination(pagination.PageNumberPagination):
    def get_paginated_response(self, data):
        return Response({
            'count': self.page.paginator.count,
            'next': self.get_next_link(),
            'previous': self.get_previous_link(),
            'total_average_price': 125000,
            'results': data,
        })


class Pricetrend(generics.ListAPIView):
    queryset = Cars.objects.annotate(...)
    serializer_class = PricetrendSerializer
    pagination_class = CustomPagination