Reputation: 253
I've been searching how to add X.objects.all().count()
result to an existing aggregate logic. I seen that Count()
will only work with a foreign key relationship, so how can I add an 'additional field' with the .count()
results to the aggregate with only writing it in one block.
This is my custom action (Does not work):
from django.db.models.functions import Coalesce
from django.db.models import Min, Avg, Max, Value as Val, IntegerField
@action(detail=False, methods=['get'])
def get_stats(self, request, pk=None):
total_ads = Ad.objects.all().count()
stats = Ad.objects.aggregate(
price_min = Coalesce(Min('price'), Val(0)),
price_avg = Coalesce(Avg('price'), Val(0.0)),
price_max = Coalesce(Max('price'), Val(0)),
ads_total = Val(total_ads, output_field=IntegerField()),
)
return Response(stats)
Error: TypeError: ads_total is not an aggregate expression
Upvotes: 1
Views: 408
Reputation: 477318
I seen that
Count()
will only work with a foreign key relationship, so how can I add an 'additional field' with the.count()
You can also Count
the primary key, which will count any non-NULL
item, you thus can use:
stats = Ad.objects.aggregate(
price_min=Coalesce(Min('price'), Val(0)),
price_avg=Coalesce(Avg('price'), Val(0.0)),
price_max=Coalesce(Max('price'), Val(0)),
ads_total=Count('pk')
)
and you thus can omit the total_ads = Ad.objects.all().count()
query, and reduce the number of queries to one.
Upvotes: 2