Django:根据更改的过滤器值计算对象?

时间:2013-10-09 18:13:26

标签: python django database-design model count

我有以下型号:

class Question(models.Model):
    question = models.CharField(max_length=100)
    detail = models.TextField(null=True, blank=True)

class PossibleAnswers(models.Model):
    question = models.ForeignKey(Question)
    value = models.CharField(max_length=200)

class Answer(models.Model):
    question = models.ForeignKey(Question)
    value = models.CharField(max_length=200)

每个Question都定义了PossibleAnswers,由用户定义。例如:问题 - 什么是最好的水果?可能的答案 - 苹果,橘子,葡萄。现在,其他用户可以Answer将问题的回复限制为PossibleAnswers

我遇到的问题是得到每个Answer的计数。选择Apple vs Orange vs Grapes有多少人回应?

Question.answer_set.filter(value="Grapes").count()会返回所有葡萄答案的计数,但如果你不知道过滤标准(本例中的葡萄)会是什么呢?由于用户定义了答案选项,并定义了有多少不同的选项,您将如何获得每个答案选项的响应计数?

3 个答案:

答案 0 :(得分:2)

首先,我会改变你的模型。您的架构未规范化。这意味着您可以在多个位置保留相同的信息(答案文本)。这本身被认为是一件坏事,但也使得设计正确的查询变得更加困难。这就是我认为你的模型应该是这样的:

class Question(models.Model):
    question = models.CharField(max_length=100)
    detail = models.TextField(null=True, blank=True)

class PossibleAnswer(models.Model):
    question = models.ForeignKey(Question)
    value = models.CharField(max_length=200)

class Answer(models.Model):
    possible_answer = models.ForeignKey(PossibleAnswers)

每次用户投票选择可能的答案时,您都会添加一个引用该答案的新Answer模型。您还可以向Answer模型添加其他字段,例如引用用户投票的外键。

然后,您将使用以下代码获取问题foo的信息(即每个可能的答案有多少实际答案):

PossibleAnswer.objects.filter(question=foo).annotate(Count('answer'))

答案 1 :(得分:0)

这会帮助你吗?

q = Question.objects.get(pk=1)
[{v: q.answer_set.filter(value=v).count()} 
           for v in [pa.value for 
                       pa in q.possibleanswers_set.all()]]

对于Question对象q存在的每个可能答案,它将返回{'possible_answer':'count'}的字典。

如果您打算在更大范围内使用它(例如所有问题对象),这不是最有效的处理方式,在这种情况下,您使用起来会好得多聚合(阅读它here)。

答案 2 :(得分:0)

您需要aggregation query

from django.db.models import Count
Question.objects.annotate(Count('answer'))