Какие есть варианты, чтобы добиться поведения фильтра по объединенным кверисетам в Django?

В общем, проблема, которая у меня есть: Мне нужен вариант или альтернативный подход для фильтрации по аннотированным полям на union queryset.

У меня есть следующие упрощенные модели:

class Course(Model):
    groups = ManyToManyField(through=CourseAssignment)


class CourseAssignment(Model):
    course = ForeignKey(Course)
    group = ForeignKey(Group)
    teacher = ForeignKey(Teacher)


class Lesson(Model):
    course = ForeignKey(Course, related_name='lessons')


class AssignmentProgress(Model):
    lesson = ForeignKey(related_name='progresses')
    course_assignment = ForeignKey(CourseAssignment)
    student = ForeignKey(Student)
    group = ForeignKey(Group)
    status = CharField(choices=(
                ('on_check', 'On check'), 
                ('complete', 'Complete'),
                ('assigned', 'Assigned'),
            ))
    deadline = DateTimeField()
    checked_date = DateTimeField()

Мне нужно вывести статистику выполнения заданий, сгруппированную по урокам и группам, для которых назначены курсы. Вот мой исходный набор запросов, обратите внимание, что уроки повторяются в конечном результате, разница в аннотированных данных:

def annotated_lessons_queryset():
    lessons = None
    for course_assignment in CourseAssignment.objects.all():
        qs = Lesson.objects.filter(
            course=course_assignment.course
        ).annotate(
            completed_progresses=Count(
                'progresses',
                filter=Q(group=course_assignment.group),
                output_field=IntegerField()
            ),
            on_check=Exists(
                AssignmentProgress.objects.filter(
                    lesson=OuterRef('id'), group=course_assignment.group, status='on_check'
                )
            )
        )
        lessons = qs if lessons is None else lessons.union(qs)
    return lessons

Здесь я могу использовать оператор | OR, потому что он возвращает только разные значения уроков. Пока это работает, пока я не попробую отфильтровать все уроки с аннотированным статусом on_check:

qs = annotated_lessons_queryset().filter(on_check=True)

Который завершается с ошибкой:

raise NotSupportedError(
django.db.utils.NotSupportedError: Calling QuerySet.filter() after union() is not supported.

Пожалуйста, предложите обходной путь или другой подход, чтобы сделать этот набор запросов фильтруемым.

Я еще не пробовал это сделать, но, как говорится в сообщении об ошибке, вы должны использовать union() последним. Это немного сложно, поскольку "Уроки могут повторяться" в этом наборе вопросов. Поэтому я бы посоветовал использовать понимание списка, чтобы получить то, что вам нужно.

qs = annotated_lessons_queryset()
filtered = [lesson for lesson in qs if lesson.on_check]
Вернуться на верх