Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django annotate count with a distinct field

Tags:

python

django

I have two models defined loosely like this:

class InformationUnit(models.Model):     username = models.CharField(max_length=255)     project = models.ForeignKey('Project')     ...  class Project(models.Model):     name = models.CharField(max_length=255) 

Now, in a view, I want to annotate all the InformationUnits that belong to a project, so I do this:

p = Project.objects.all().annotate(Count('informationunit') 

which works just ok.

Furthermore, I want to know, in each project, how many distinct usernames participate. That is, count how many distinct usernames are there in the InformationUnits that compose one project. I have tried the following, but it simply counts the number of InformationUnit, regardless of the username:

p = Project.objects.all().annotate(Count('informationunit__username') 

Note that username is not an object, it is a string. Is there a clean way to do this or should I create a more complicated code based on loops and spaghetti code :P

Thanks a lot!

like image 634
fenomenoxp Avatar asked Oct 30 '12 18:10

fenomenoxp


People also ask

What is distinct () in Django QuerySet?

distinct() Returns a new QuerySet that uses SELECT DISTINCT in its SQL query. This eliminates duplicate rows from the query results. By default, a QuerySet will not eliminate duplicate rows.

How do I get unique values in Django query?

We can use a distinct() query method at the end or in between queryset and with other regular Django query methods like all(), values(), etc…

What is the difference between aggregate and annotate in Django?

Unlike aggregate() , annotate() is not a terminal clause. The output of the annotate() clause is a QuerySet ; this QuerySet can be modified using any other QuerySet operation, including filter() , order_by() , or even additional calls to annotate() .

What does .all do in Django?

Definition of the all() manager method: all() Returns a copy of the current QuerySet (or QuerySet subclass). This can be useful in situations where you might want to pass in either a model manager or a QuerySet and do further filtering on the result.


2 Answers

Count can take a distinct argument, like so:

p = Project.objects.all().annotate(Count('informationunit__username',                                           distinct=True)) 

This doesn't seem to be documented, but you can find it in the source for Count.

like image 186
spencer nelson Avatar answered Sep 22 '22 09:09

spencer nelson


If you just want to count the distinct values, you can use the distinct() and count() functions:

count = Project.objects.values('informationunit__username').distinct().count() 
like image 37
Mouscellaneous Avatar answered Sep 20 '22 09:09

Mouscellaneous