Django equivalent for count and group by

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.


Asked by: Kellan786 | Posted: 05-10-2021






Answer 1

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'))

Answered by: Steven270 | Posted: 06-11-2021



Answer 2

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.

Answered by: Ada99 | Posted: 06-11-2021



Answer 3

(Update: Full ORM aggregation support is now included in Django 1.1. True to the below warning about using private APIs, the method documented here no longer works in post-1.1 versions of Django. I haven't dug in to figure out why; if you're on 1.1 or later you should use the real aggregation API anyway.)

The core aggregation support was already there in 1.0; it's just undocumented, unsupported, and doesn't have a friendly API on top of it yet. But here's how you can use it anyway until 1.1 arrives (at your own risk, and in full knowledge that the query.group_by attribute is not part of a public API and could change):

query_set = Item.objects.extra(select={'count': 'count(1)'}, 
                               order_by=['-count']).values('count', 'category')
query_set.query.group_by = ['category_id']

If you then iterate over query_set, each returned value will be a dictionary with a "category" key and a "count" key.

You don't have to order by -count here, that's just included to demonstrate how it's done (it has to be done in the .extra() call, not elsewhere in the queryset construction chain). Also, you could just as well say count(id) instead of count(1), but the latter may be more efficient.

Note also that when setting .query.group_by, the values must be actual DB column names ('category_id') not Django field names ('category'). This is because you're tweaking the query internals at a level where everything's in DB terms, not Django terms.

Answered by: Sydney421 | Posted: 06-11-2021



Answer 4

How's this? (Other than slow.)

counts= [ (c, Item.filter( category=c.id ).count()) for c in Category.objects.all() ]

It has the advantage of being short, even if it does fetch a lot of rows.


Edit.

The one query version. BTW, this is often faster than SELECT COUNT(*) in the database. Try it to see.

counts = defaultdict(int)
for i in Item.objects.all():
    counts[i.category] += 1

Answered by: Wilson746 | Posted: 06-11-2021



Similar questions

python - Django equivalent of COUNT with GROUP BY

I know Django 1.1 has some new aggregation methods. However I couldn't figure out equivalent of the following query: SELECT player_type, COUNT(*) FROM players GROUP BY player_type; Is it possible with Django 1.1's Model Query API or should I just use plain SQL?


python - What is the django equivalent of this SQL query?

I am very new to django and I am tryin to accomplish some repetitive tasks. I was wondering what would be the django equivalent of the following tasks. I want to select all values that fall within a certain date range. Eg: Let there be a table called exam scores User Physics Chemistry Mathematics Total Date bill 98 94 Pass 284 02/03/2013 murray 0 ...


python - Django equivalent of Rails cancan and devise

I did projects with django back a while ago and switched to rails. I found lots of cool thing in rails. I need to add some features back to django project. Are there Django equivalent of Rails cancan and devise ? Is there Django equivalent of Rails scheduler gem? UPDATE For django permission framework I have to specify at each view something like


python - Django ORM equivalent for 'or'?

This question already has answers here:


python - MYSQL query equivalent in django

I have a django project with 2 models called wca and identifiers, I am wanting to update a field called 'secid' within identifiers model pulled from the equivalent field in wca model where code from identifiers model matches isin field in wca model. Models class Identifier(TimeStampMixin, models.Model): secid = models.IntegerField(default=0, db_index=True) code_type = models.C...


stdin - Python equivalent of Perl's while (<>) {...}?

I write a lot of little scripts that process files on a line-by-line basis. In Perl, I use while (&lt;&gt;) { do stuff; } This is handy because it doesn't care where the input comes from (a file or stdin). In Python I use this if len(sys.argv) == 2: # there's a command line argument sys.stdin = file(sys.argv[1]) for line in sys.stdin.readlines(): do stuf...


Python "Event" equivalent in Java?

What's the closest thing in Java (perhaps an idiom) to threading.Event in Python?


python - Django equivalent of COUNT with GROUP BY

I know Django 1.1 has some new aggregation methods. However I couldn't figure out equivalent of the following query: SELECT player_type, COUNT(*) FROM players GROUP BY player_type; Is it possible with Django 1.1's Model Query API or should I just use plain SQL?


Python equivalent of Jstack?

Is there a python equivalent of jstack? I've got a hung process and I really want to see what it's up to because I have yet to reproduce the defect in development.


Java equivalent of Python repr()?

Is there a Java method that works like Python's repr? For example, assuming the function were named repr, "foo\n\tbar".repr() would return "foo\n\tbar" not foo bar as toString does.


Python equivalent to atoi / atof

Python loves raising exceptions, which is usually great. But I'm facing some strings I desperately want to convert to integers using C's atoi / atof semantics - e.g. atoi of "3 of 12", "3/12", "3 / 12", should all become 3; atof("3.14 seconds") should become 3.14; atoi(" -99 score") should become -99. Python of course has atoi and atof functions, which behave nothing like atoi and atof and exactly like Python's own int...


python - Lua equivalent to shlex?

Is there a Lua equivalent for python's shlex library?


Python equivalent of IDL's stop and .reset

I'm relatively new to python but have a bit of experience using IDL. I was wondering if anyone knows if there are equivalent commands in python for IDL's stop and .reset commands. If I'm running some IDL script I wrote that I put a stop command in, essentially what it does is stop the script there and give me access to the command line in the middle of the script. So I have access to all the functions and variables ...


python equivalent of GNU 'cat' that shows unique lines

Has anyone written the GNU cat command in python and would be willing to share? GNU cat actually does quite a bit &amp; I don't really feel like re-inventing the wheel today. Yes, I did do a google search &amp; and after reading


css - Ruby LESS gem equivalent in Python

The Ruby LESS gem looks awesome - and I am working on a Python/Pylons web project where it would be highly useful. CSS is, as someone we're all familiar with recently wrote about, clunky in some important ways. So I'd like to make it easier on myself. Is there an exi...


python - Pythonic equivalent of unshift or redo?

I'm learning Python, and I have a situation where I want to consume items from an iterator. The tricky part is that under certain conditions, I want to "un-iterate." That is, put an item back onto the front of the iterator before I loop. For example, suppose I'm picking apples from a tree. My fruit basket can only hold 10kg before it needs to be emptied. But I have to pick each apple before I can weigh it and d...


Is there a Python equivalent of Perl's x operator (replicate string)?

In Perl, I can replicate strings with the 'x' operator: $str = "x" x 5; Can I do something similar in Python?


Python's os.execvp equivalent for PHP

I've got a PHP command line program running. And I want to connect to a mysql shell straight from PHP. I've done this before in Python using os.execvp But I can't get the same thing to work in PHP. I've tried the following functions: system passthru exec shell_exec example: system('mysql -u root -pxxxx db_name'); But they all ...


Ruby equivalent of Python's "dir"?

In Python we can "dir" a module, like this: &gt;&gt;&gt; import re &gt;&gt;&gt; dir(re) And it lists all functions in the module. Is there a similar way to do this in Ruby?


Is there a Python news site that's the near equivalent of RubyFlow?

I really like the format and type of links from RubyFlow for Ruby related topics. Is there an equivalent for Python that's active? There is a PythonFlow, but I think it's pretty much dead. I don't really like http://planet.python.org/ because there's lots o...


Java Servlet Filter Equivalent in Ruby [on Rails] and PHP?

Not sure if the terminology is correct, but are there rough equivalents to Java Servlet Filters in Ruby and PHP ? Are they actual concrete classes ? I assume there is also a number of common web app libraries/frameworks in Python. Is there an equivalent there ? Thanks. === ADDENDUM === On the good advice of


python - Is there a Vim equivalent to the Linux/Unix "fold" command?

I realize there's a way in Vim to hide/fold lines, but what I'm looking for is a way to select a block of text and have Vim wrap lines at or near column 80. Mostly I want to use this on comments in situations where I'm adding some text to an existing comment that pushes it over 80 characters. It would also be nice if it could insert the comment marker at the beginning of the line when it wraps too. Also I'd pre...


python - Ruby equivalent of virtualenv?

Is there something similar to the Python utility virtualenv? Basically it allows you to install Python packages into a sandboxed environment, so easy_install django doesn't go in your system-wide site-packages directory, it would go in the virtualenv-created directory. For example: $ virtualenv test New python...


What's the idiomatic Python equivalent to Django's 'regroup' template tag?

http://docs.djangoproject.com/en/dev/ref/templates/builtins/#regroup I can think of a few ways of doing it with loops but I'd particularly like to know if there is a neat one-liner.


Do Python lists have an equivalent to dict.get?

I have a list of integers. I want to know whether the number 13 appears in it and, if so, where. Do I have to search the list twice, as in the code below? if 13 in intList: i = intList.index(13) In the case of dictionaries, there's a get function which will ascertain membership and perform look-up with the same search. Is there something similar for lists?






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top