Home > Software engineering >  Django Group by multiple times
Django Group by multiple times

Time:10-18

In my Django models, I have

class Tracker(models.Model):
    grade = models.ForeignKey(Grade, on_delete=models.CASCADE)
    teacher = models.ForeignKey(User, on_delete=models.CASCADE)
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    BREAK_TYPE_CHOICES = [
        ('1', 'Toilet Pass'),
        ('2', 'Hall Pass'),
        ('3', 'Doctor Pass'),
    ]
    break_type = models.CharField(max_length=10, choices=BREAK_TYPE_CHOICES)
    start_date_time = models.DateTimeField(auto_now_add=True)
    end_date_time = models.DateTimeField(auto_now=True)
    status = models.BooleanField(default=False)

I need to find all the breaks given in a day, group by teachers with a break up on the basis of break type.

Currently, I can get breaks given in a day and group them by teachers.

breaks_today = Tracker.objects.filter(status=True, start_date_time__gte=date_from, end_date_time__lte=date_to)
breaks_today = breaks_today.values('teacher').order_by('teacher').annotate(count=Count('teacher'))

How do I proceed with the next step, i.e. group by break types, then group by teacher?

CodePudding user response:

You can pass two fields in the .values(…) clause [Django-doc]:

breaks_today.values('teacher', 'break_type').order_by(
    'teacher', 'break_type'
).annotate(count=Count('teacher'))

This will then make dictionaries with three items: the teacher, the break_type and the corresponding count.

You can post-process these to:

from itertools import groupby
from operator import itemgetter

result = {
    k: {
        k2: list(map(itemgetter('count'), v))
        for k2, v in groupby(itemgetter('break_type'), vs)
    }
    for k, vs in groupby(itemgetter('teacher'), breaks_today)
}
  • Related