Alex
Alex

Reputation: 42

Django aggregation / annotation

I know this is probably a really simple question, but I've been trying to solve it for ages now and keep failing!

I have two models:

class Subject(models.Model):
    name = models.CharField(max_length=200)

class Pupil(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    active = models.BooleanField(default=0, db_index=True)
    takes_subject = models.ManyToManyField(Subject)

Each pupil can take many subjects. Finding out how many pupils take each subject is easy, but I want to find out how many pupils take multiple subjects. Something like:

Subjects taken |  Number of pupils
===============|==================
4              |  20
3              |  15
2              |  7
1              |  38

That way I can know that say 15 pupils are taking 3 subjects while 38 pupils are taking 1 subject.

How do I achieve this?

Thanks in advance,

Alex

Upvotes: 0

Views: 57

Answers (1)

C14L
C14L

Reputation: 12548

from collections import Counter
Counter(Pupil.objects.annotate(
    count=Count('takes_subject')).values_list('count', flat=True))

That gets a list from Pupil counting how many subjects each student takes, e.g. [4, 5, 4, 4, 6,...].

Then let Counter() count how often each number occurs, and return a dict(), e.g. {4: 3, 5: 1, 6: 1, ...}.

Upvotes: 1

Related Questions