Python Django:根据更改的筛选器值计算对象?
我有以下型号:Python Django:根据更改的筛选器值计算对象?,python,django,database-design,model,count,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(m
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.answer\u set.filter(value=“Grapes”).count()?由于用户定义了答案选项,并定义了有多少不同的选项,您如何获得每个答案选项的响应计数?这对您有帮助吗
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()]]
对于存在于问题对象q中的每个可能答案,它将返回一个{‘可能的答案’:‘计数’}字典
但是,如果您打算在更大范围内使用它(比如对所有问题对象),这并不是最有效的方法,在这种情况下,您最好使用聚合(了解它)。您需要:
首先我会改变你的模型。您的架构未规范化。这意味着您在多个位置保留相同的信息(答案的文本)。这本身被认为是一件坏事,但也使得设计正确的查询变得更加困难。我认为您的模型应该是这样的:
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)
每次用户投票选择一个可能的答案时,您都会添加一个新的答案
模型来引用该可能的答案。您还可以向答案
模型添加其他字段,例如引用用户投票的外键
然后,您将使用以下代码获取问题foo
的信息(即每个可能答案的实际答案数):
PossibleAnswer.objects.filter(question=foo).annotate(Count('answer'))
虽然功能强大,但这可能会给数据库带来相当大的开销。这难道不是要计算每个问题的所有答案,而不是为每个可能的答案提供不同的数字吗?+1这真是太好了。然而,将模型命名为问题、答案(而不是可能答案)和数量或选择或其他东西(而不是答案)不是更好、更清晰吗?我的意思是,在这个模式中,答案模型的功能就像一个投票或类似的模型,因为它只是用于计数,实际上,模型名称应该是描述单个对象的单数名词,所以我不会考虑“计数”或“选择”一个好名字的模型。但是你是对的,如果我们确信答案
模型只是用于计数,那么这就不是最好的解决方案。在这种情况下,我会将Answer
模型一起去掉,并将count
字段添加到PossibleAnswer
模型中(然后确实应该将其重命名为Answer
)。然后,每次用户选择答案时,该字段都应该递增。但是,我没有选择该解决方案,因为我认为很可能每次用户投票时都会记录其他信息,如时间、用户名或用户ip。是的,“计数”或“选择”都不好,我真的想不出什么,但问题是,现在的名称令人困惑,不能很好地表达他们记录的数据的本质。这是一个好问题。答案是:answer.objects.filter(可能的\u-answer\u-question=foo.count()
PossibleAnswer.objects.filter(question=foo).annotate(Count('answer'))