Django annotation with nested filter

前端 未结 3 1030
萌比男神i
萌比男神i 2021-01-01 12:57

Is it possible to filter within an annotation?

In my mind something like this (which doesn\'t actually work)

Student.objects.all().annotate(Count(\'at

3条回答
  •  别那么骄傲
    2021-01-01 13:26

    You are correct - django does not allow you to filter the related objects being counted, without also applying the filter to the primary objects, and therefore excluding those primary objects with a no related objects after filtering.

    But, in a bit of abstraction leakage, you can count groups by using a values query.

    So, I collect the absences in a dictionary, and use that in a loop. Something like this:

    # a query for students
    students = Students.objects.all()
    # a query to count the student attendances, grouped by type.
    attendance_counts = Attendence(student__in=students).values('student', 'type').annotate(abs=Count('pk'))
    # regroup that into a dictionary {student -> { type -> count }}
    from itertools import groupby
    attendance_s_t = dict((s, (dict(t, c) for (s, t, c) in g)) for s, g in groupby(attendance_counts, lambda (s, t, c): s))
    # then use them efficiently:
    for student in students:
        student.absences = attendance_s_t.get(student.pk, {}).get('Excused', 0)
    

提交回复
热议问题