1

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

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.