How to aggregate filtered listapiview queryset and return value once
How to perform aggregations on filtered querysets and return the value only once?
My existing code below. In the serializer, of course PZ.objects.all() makes it aggregate all items. I don't know how to get the queryset from the serializer level. To make the total value appear once, it would be a good idea to add a field in the view. However, overriding def list(): makes the filtering stop working.
I need this because I am working on a table that shows documents with filtering capabilities. In addition, there will be pagination. After selecting, for example, a creation date range, the values of the documents must be summed.
View:
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']
Response:
[
{
"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"
}
]
Desired response:
[
"net_value_sum": 16.0,
{
"id": 41,
"status": "C",
"net_value": "6.00"
},
{
"id": 42,
"status": "S",
"net_value": "10.00"
}
]
I managed to find a solution to this problem myself. You need to override the 'def list():' method while returning the filtered queryset. Then on this queryset in the view we return with the aggregated value. The code looks like this:
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])