Как объединить отфильтрованный список listapiview queryset и вернуть значение один раз

Как выполнить агрегацию на отфильтрованных наборах запросов и вернуть значение только один раз?

Мой существующий код ниже. В сериализаторе, конечно же, PZ.objects.all() заставляет его агрегировать все элементы. Я не знаю, как получить кверисет с уровня сериализатора. Чтобы общее значение отображалось один раз, было бы неплохо добавить поле в представлении. Однако переопределение def list(): заставляет фильтрацию перестать работать.

Мне это нужно, потому что я работаю над таблицей, которая показывает документы с возможностью фильтрации. Кроме того, будет присутствовать пагинация. После выбора, например, диапазона дат создания, значения документов должны суммироваться.

Вид:

class PZListAPIView(ListAPIView):
    queryset = PZ.objects.all()
    serializer_class = PZModelSerializer
    filterset_fields = {
        'id': ['exact', 'in', 'contains', 'range']
    }

Serializer:

class PZModelSerializer(serializers.ModelSerializer):
    net_value_sum = serializers.SerializerMethodField('get_net_value_sum')
    class Meta:
        model = PZ
        fields = '__all__'
    
    def get_net_value_sum(self, obj):
        return PZ.objects.aggregate(Sum('net_value'))['net_value__sum']

Ответ:

[
    {
        "id": 41,
        "net_value_sum": 28.0,
        "status": "C",
        "net_value": "6.00"
    },
    {
        "id": 42,
        "net_value_sum": 28.0,
        "status": "S",
        "net_value": "10.00"
    }
]

Желаемый ответ:

[
    "net_value_sum": 16.0,
    {
        "id": 41,
        "status": "C",
        "net_value": "6.00"
    },
    {
        "id": 42,
        "status": "S",
        "net_value": "10.00"
    }
]

Мне удалось найти решение этой проблемы самостоятельно. Нужно переопределить метод 'def list():' при возврате отфильтрованного набора запросов. Затем по этому кверисету в представлении возвращаем агрегированное значение. Код выглядит следующим образом:

class PZListAPIView(ListAPIView):
    queryset = PZ.objects.all()
    serializer_class = PZModelSerializer
    filterset_fields = {
        'id': ['exact', 'in', 'contains', 'range']
    }
    
    def get_queryset(self):
        return PZ.objects.all()

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        
        net_value = queryset.aggregate(Sum('net_value'))['net_value__sum']
        return Response([{'net_value': net_value},serializer.data])
Вернуться на верх