В Django, как аннотировать внутри поля M2M?

У меня есть эти модели:

class Convocacao(models.Model):
    cursos = models.ManyToManyField(Curso)

class RegistroConvocacao(models.Model):
    aluno = models.ForeignKey(Aluno)
    convocacao = models.ForeignKey(Convocacao)
    tipo = models.IntegerField(choices=TiposConvocacao)

class Aluno(models.Model):
    curso = models.ForeignKey(Curso)

Затем я получаю объект Convocacao:

obj = get_object_or_404(Convocacao, pk=pk)

Теперь я хочу использовать annotate внутри obj.cursos, чтобы суммировать tipo RegistroConvocacao.

Что-то вроде:

cursos = obj.cursos.all()
cursos = cursos.annotate(       
    total_ingressantes=obj.registroconvocacao_set.filter(
            aluno__curso__in=obj.cursos, 
            tipo_convocacao=RegistroConvocacao.TIPO_CONVOCACAO_INGRESSANTE
    ).count()
)

Но он выдает ошибку: TypeError: 'ManyRelatedManager' object is not iterable

Я хочу сделать что-то вроде:

for curso in obj.cursos.all():
    total = curso.total_ingressantes
    ...

Я получил его, используя Prefetch:

obj = get_object_or_404(
        Convocacao.objects.prefetch_related(
            Prefetch(
                "cursos",
                queryset=Curso.objects.annotate(
                    total_ingressantes=Sum(
                        Case(
                            When(
                                Q(
                                    convocacao__registroconvocacao__tipo_convocacao=RegistroConvocacao.TIPO_CONVOCACAO_INGRESSANTE
                                )
                                & Q(convocacao__registroconvocacao__aluno__curso=F("id")),
                                then=1,
                            ),
                            default=0,
                        )
                    ),
                    total_concluintes=Sum(
                        Case(
                            When(
                                Q(
                                    convocacao__registroconvocacao__tipo_convocacao=RegistroConvocacao.TIPO_CONVOCACAO_CONCLUINTE
                                )
                                & Q(convocacao__registroconvocacao__aluno__curso=F("id")),
                                then=1,
                            ),
                            default=0,
                        )
                    ),
                ).order_by("diretoria__setor__uo"),
            )
        ),
        pk=pk,
    )
Вернуться на верх