Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django equivalent for count and group by

Tags:

python

django

I have a model that looks like this:

class Category(models.Model):     name = models.CharField(max_length=60)  class Item(models.Model):     name = models.CharField(max_length=60)     category = models.ForeignKey(Category) 

I want select count (just the count) of items for each category, so in SQL it would be as simple as this:

select category_id, count(id) from item group by category_id 

Is there an equivalent of doing this "the Django way"? Or is plain SQL the only option? I am familiar with the count( ) method in Django, however I don't see how group by would fit there.

like image 409
Sergey Golovchenko Avatar asked Nov 29 '08 18:11

Sergey Golovchenko


People also ask

How to GROUP BY in python Django?

In Django, we can use the GROUP BY statement by using the aggregate function or by using some built-ins. Also, the GROUP BY statement and the aggregate function are always used in combinations to group the result set.

How do you count in Django?

Use Django's count() QuerySet method — simply append count() to the end of the appropriate QuerySet. Generate an aggregate over the QuerySet — Aggregation is when you "retrieve values that are derived by summarizing or aggregating a collection of objects." Ref: Django Aggregation Documentation.

How do you annotate in Django?

Appending the annotate() clause onto a QuerySet lets you add an attribute to each item in the QuerySet, like if you wanted to count the amount of articles in each category. However, sometimes you only want to count objects that match a certain condition, for example only counting articles that are published.


2 Answers

Here, as I just discovered, is how to do this with the Django 1.1 aggregation API:

from django.db.models import Count theanswer = Item.objects.values('category').annotate(Count('category')) 
like image 173
michael Avatar answered Sep 26 '22 21:09

michael


Since I was a little confused about how grouping in Django 1.1 works I thought I'd elaborate here on how exactly you go about using it. First, to repeat what Michael said:

Here, as I just discovered, is how to do this with the Django 1.1 aggregation API:

from django.db.models import Count theanswer = Item.objects.values('category').annotate(Count('category')) 

Note also that you need to from django.db.models import Count!

This will select only the categories and then add an annotation called category__count. Depending on the default ordering this may be all you need, but if the default ordering uses a field other than category this will not work. The reason for this is that the fields required for ordering are also selected and make each row unique, so you won't get stuff grouped how you want it. One quick way to fix this is to reset the ordering:

Item.objects.values('category').annotate(Count('category')).order_by() 

This should produce exactly the results you want. To set the name of the annotation you can use:

...annotate(mycount = Count('category'))... 

Then you will have an annotation called mycount in the results.

Everything else about grouping was very straightforward to me. Be sure to check out the Django aggregation API for more detailed info.

like image 33
Daniel Avatar answered Sep 26 '22 21:09

Daniel