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