Reputation: 3484
I'm trying to limit the number of queries I perform on a page. The queryset returns the objects created within the last 24 hours. I then want to filter that queryset to count the objects based upon a field.
Example:
cars = self.get_queryset()
volvos_count = cars.filter(brand="Volvo").count()
mercs_count = cars.filter(brand="Merc").count()
With an increasing number of brands (in this example), the number of queries grows linearly with the number of brands that must be queried.
How can you make a single query for the cars that returns a dict of all of the unique values for brand and the number of instances within the queryset?
Result:
{'volvos': 4, 'mercs': 50, ...}
Thanks!
EDIT:
Of the comments so far, they have been close but not quite on the mark. Using a values_list('brand', flat=True)
will return the brands. From there you can use
from collections import Counter
To return the totals. It would be great if there is a way to do this from a single query, but maybe it isn't possible.
Upvotes: 1
Views: 4655
Reputation: 1
SELECT brand, COUNT(*) as total
FROM cars
GROUP BY brand
ORDER BY total DESC
Equivalent:
cars.objects.all().values('brand').annotate(total=Count('brand')).order_by('total')
Upvotes: 0
Reputation: 600041
To generate a count for each distinct brand, you use values
in conjunction with annotate
.
totals = cars.values('brand').annotate(Count('brand'))
This gives you a queryset, each of whose elements is a dictionary with brand
and brand__count
. You can convert that directly into a dict with the format you want:
{item['brand']: item['brand__count'] for item in totals}
Upvotes: 4