Django 1.10.7 ORM使用多个到多个字段的条件计数来注释查询

时间:2018-04-01 05:48:23

标签: django

我在使用django的annnotate函数从多个到多个字段获取条件计数时遇到了问题。

我有这3个型号:

class Answer(models.Model):
    """
    This model represents an answer to an open question. It just contains
    the answer text and the question it answers.
    """
    answer_description = models.CharField(max_length=1500, blank=True, null=True)
    question = models.ForeignKey(Question)
    instrument_submission = models.ForeignKey(InstrumentSubmission)

class MultipleChoiceAnswer(Answer):
    choices = models.ManyToManyField(QuestionChoice)

class QuestionChoice(models.Model):
    name = models.CharField(max_length=300)
    question = models.ForeignKey(MultipleChoiceQuestion)
    explanation_needed = models.BooleanField(default=False)
    is_correct = models.BooleanField(default=False)
    ordinal = models.IntegerField(blank=True, null=True)
    select_all = models.BooleanField(default=False)
    no_answer = models.BooleanField(default=False)

我想要做的是获取所有MultipleChoiceAnswers选项字段的总数,以及正确选择的额外计数(具有属性is_correct=True的那些)

作为一个例子,我有一个MultipleChoiceAnswer有2个选择相关。 一个使用is_correct=True,另一个使用is_correct=False

然后我运行了以下测试:

In [4]: x=MultipleChoiceAnswer.objects.filter(pk=33420)

In [11]: for ans in x:
    ...:     for c in ans.choices.all():
    ...:         print c.is_correct
    ...:         
True
False

In [7]: x=x.annotate(c=Count('choices'),
   ...: 
   ...: correct=Count('choices',filter=Q(is_correct=True)))

In [8]: for a in x:
   ...:     print a.c
   ...:     print a.correct
   ...:     
2
2

我希望看到2然后是1.但是伯爵并没有按照我的预期行事。

有谁能帮我发现问题?

1 个答案:

答案 0 :(得分:3)

filter参数被添加到Django 2中的聚合中,因此它在Django 1.10中不起作用。但是,对于使用conditional expressions的更复杂的查询,您可以实现相同的目的:

from django.db.models import Case, Count, IntegerField, When

ans.annotate(correct=Sum(
    Case(
        When(choices__is_correct=True, then=1),
        default=0,
        output_field=IntegerField(),
    )
))

这基本上将所有正确的选项相加,并为每个答案返回它们的计数。