Как добавить дополнительные поля вне списка элементов в modelView? (например, счетчик для пагинации)

Я ищу лучший способ добавить дополнительные поля в список get, возвращаемый ModelView.

У меня следующая модель:

class Sale(models.Model):
    total = models.FloatField(_("Total"))
    name = models.CharField(_("Name"))
    [...]

Когда я делаю get list для этой модели, я получаю следующий json:

{

    "count": 0,
    "next": "http://example.com",
    "previous": "http://example.com",
    "results": 
    [
        {
            "id": 0,
            "name": "example",
            "total": 0,
            [...]
         }
    ]
}

Я хотел бы добавить в результат 2 поля min_total и max_total (на том же уровне, что и "count").

Пример:

{

    "count": 0,
    "next": "http://example.com",
    "previous": "http://example.com",
    "min_total": 0,
    "max_total": 100,
    "results": 

    [
        {

            "id": 0,
            "name": "example",
            "total": 100,
            [...]
         }
    ]
}

Мое мнение:

class SaleViewSet(viewsets.ReadOnlyModelViewSet):
    """
    A simple ViewSet for listing or retrieving sales.
    """
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filter_fields = ['client', 'machine', 'date_time', 'total']
    ordering_fields = '__all__'
    
    def get_serializer_class(self):
        if hasattr(self, 'action') and self.action == 'list':
            return SaleListSerializer
        if hasattr(self, 'action') and self.action == 'retrieve':
            return SaleRetrieveSerializer
        return SaleSerializer  
       
    def get_queryset(self):
        queryset = Sale.objects.all().select_related('client')
        user = self.request.user
        if user.is_staff:
            cache_key = 'list_sale_sales'
        else:
            queryset = queryset.filter(client=user.profil.client)
            cache_key = f'list_sale_sales_client_{user.profil.client.pk}'
        
        return cache.get_or_set(cache_key, queryset, 60)

Чтобы получить эти 2 значения, я просто должен сделать эти 2 запроса: Sale.objects.all().aggregate(min=Min("total")) и Sale.objects.all().aggregate(max=Max("total"))

Какой лучший способ правильно добавить эти 2 поля?

Вы можете переопределить метод list в viewset:

def list(self, request, *args, **kwargs):
    response = super().list(request, *args, **kwargs)
    response.data['min_total'] = Sale.objects.all().aggregate(min=Min("total"))
    response.data['max_total'] = Sale.objects.all().aggregate(max=Max("total"))
    return response

Примечание: Это даст минимальное/максимальное значение из всех записей о продаже. Чтобы получить минимальное/максимальное значение из отфильтрованных данных на основе вашей функции get_queryset:

response.data['min_total'] = self.get_queryset().aggregate(min=Min("total"))
Вернуться на верх