Как добавить дополнительные поля вне списка элементов в 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"))