让我们说我有一个简单的投票表格,有不同的答案。
人们可以从一个IP多次投票。我可以很容易地找到一个给定答案得到多少票 - a.vote_set.all().count()
(不受1个IP的投票限制)我也可以找出有多少票,考虑到来自1个IP的限制1票 - {{1 (一个IP = 1的投票限制)
如果我想从1个IP(极限= 10)计算多达10票,如何获得给定答案的总票数?
澄清我的问题:我需要一个Django orm查询来获得给定答案的所有投票 - 但是有了这个条件,我想从一个IP计算多达10票。例: 答案A得到100票。 100票来自以下知识产权(一人投票或其中几人共享公共知识产权):
1)120.x.x.x - 20票2)121.x.x.x - 50票3)122.x.x.x - 10 票4)123.x.x.x - 5票5)124.x.x.x - 15票
我希望查询返回45票:来自IP 1的10票)(10,不是20,因为10是限制),10来自2),10来自3),5来自4)最后10来自5
我事先并不知道选民使用了多少IP。 请不要告诉我这个用例是不可能的 - 这是真的,我必须这样做并且卡住了:P
答案 0 :(得分:1)
好吧,这不是一个简短的答案,但我在Django shell中验证了这一点,并且从我运行的几个测试中它似乎正在计数。
我假设你有一个可以简化的模型:
class Answer(models.Model):
answertext = models.CharField(max_length=200)
class Vote(models.Model):
answer = models.ForeignKey(Answer, on_delete=None)
ip = models.CharField(max_length=15)
如果我理解你的问题,我们现在想要计算一个答案的投票数 - 限制一个IP投票的次数为10次。
我将分解各种组件并在最后给出完整的陈述。
首先,我们过滤掉一个特定的答案。你可能想要一些具体的东西 - 我只是拿了所有的“是”答案。我们用计数进行注释,以便我们得到所有的肯定答案,其中包含投票IP和这些IP投票的次数:
Vote.objects.filter(answer__answertext='Yes').values('ip').annotate(ipcount=Count('id'))
接下来,我们需要将计数大于10的IP限制为最多10票。我们使用Case和When表达式来完成此操作。基本上,这表示给我们一个新的字段,当计数小于或等于10时,等于来自IP的投票数,如果IP投票数大于10,则将新字段限制为10。
.annotate(limitedipcount = Case(
When(ipcount__lte=10, then='ipcount'),
When(ipcount__gt=10, then=10),
output_field=IntegerField())
)
最后,我们需要总结一下这个新的'limitedipcount',我们用一个简单的聚合表达式做到这一点:
.aggregate(totallimitedipcount=Sum('limitedipcount'))
如果你把所有这些放在一起就会得到这样的东西:
Vote.objects.filter(answer__answertext='Yes')
.values('ip')
.annotate(ipcount=Count('id'))
.annotate(limitedipcount = Case(
When(ipcount__lte=10, then='ipcount'),
When(ipcount__gt=10, then=10),
output_field=IntegerField())
)
.aggregate(totallimitedipcount=Sum('limitedipcount'))
答案 1 :(得分:0)
好的,所以我最终编写了一个带有限制作为参数的辅助函数(默认为None),它构建了字典{ip1:num_of_votes1,ip2:num_of_votes2}。为了构建这个字典,该函数遍历给定答案的所有投票,每次检查投票的ip,判断ip是否已经在字典中,是否已达到给定IP的限制,如果没有 - 增加给定键的值。最后,我总结了值 - sum(my_dict.values())
并将其返回。
这可能是一个非常强力的解决方案,所以如果有人知道更好的事情,请发布。