Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在django按类似挖掘的评级订购_Python_Django_Rating System - Fatal编程技术网

Python 在django按类似挖掘的评级订购

Python 在django按类似挖掘的评级订购,python,django,rating-system,Python,Django,Rating System,我有两种型号: class Post(models.Model): #some fields pass class Vote(models.Model): post = mdoels.ForeignKey(Post) value = models.IntegerField() 投票的值可以是1或-1(用户可以向上或向下投票) 我怎样才能得到一个按评级排序的帖子列表?我认为这应该是可行的: Vote.objects.values_list('post', fla

我有两种型号:

class Post(models.Model):
    #some fields
    pass

class Vote(models.Model):
    post = mdoels.ForeignKey(Post)
    value = models.IntegerField()
投票的值可以是1或-1(用户可以向上或向下投票)


我怎样才能得到一个按评级排序的帖子列表?

我认为这应该是可行的:

Vote.objects.values_list('post', flat=True).order_by('value')
要颠倒顺序,请执行以下操作:

Vote.objects.values_list('post', flat=True).order_by('-value')
更新

因为post是一个
外键
post
,让我们假设您的模型是这样的:

class Post(models.Model):
    post_id = models.AutoField(primary_key=True)
    post_name = models.CharField(max_length=30, unique=True)
因此,这应该是可行的,它将返回以下名称:

 Vote.objects.values_list('post__post_name', flat=True).order_by('value')
注_

如果要对列表进行查询并出现错误,只需将其转换为列表:

list(Vote.objects.values_list('post__post_name', flat=True).order_by('value')))

您必须使用注释

然后您需要导入
Sum
,并可以获得按其
vote\u total
排序的帖子列表,如:

from django.db.models import Sum
Post.objects.annotate(vote_total=Sum('vote__value')).order_by('-vote_total')
编辑:
这里有一个例子。创建多个post对象和Vote对象

Post.objects.get_or_create(id=1, name="post1")
Post.objects.get_or_create(id=2, name="post2")
Post.objects.get_or_create(id=3, name="post3")
Post.objects.get_or_create(id=4, name="post4")
Vote.objects.get_or_create(id=1, post_id=2, value=1, type="AW")
Vote.objects.get_or_create(id=2, post_id=2, value=1, type="AW")
Vote.objects.get_or_create(id=3, post_id=2, value=1, type="US")
Vote.objects.get_or_create(id=4, post_id=2, value=1, type="US")
Vote.objects.get_or_create(id=5, post_id=3, value=-1, type="AW")
Vote.objects.get_or_create(id=6, post_id=3, value=-1, type="AW")
Vote.objects.get_or_create(id=7, post_id=4, value=-1, type="AW")
然后
posts=Post.objects.annotate(vote_total=Sum('vote_value'))。order_by('-vote_total')
将导致
[(Post.name,Post.vote_total)对于Post-in-posts]
被删除

[(u'post2', 4), (u'post4', -1), (u'post3', -2), (u'post1', None)]
这有一个问题,因为没有帖子的事情会在最后发生。正如django的
Sum
aggregation函数将no条目的和视为None,而不是0。如果您最初给每个帖子一个值为0(或像reddit的系统一样为1)的投票,那么这个问题就可以解决了,您不会得到无:例如:

for p in Post.objects.all():
    Vote.objects.get_or_create(post_id=p.id, value=0)
然后你会得到

>>> [(p.name, p.vote_total) for p in
     Post.objects.annotate(vote_total=Sum('vote__value')).order_by('-vote_total')]
[(u'post2', 4), (u'post1', 0), (u'post4', -1), (u'post3', -2)]

编辑:根据关于不同投票类型的评论,将类型添加到投票模型(如上所述)。 您应该能够执行以下操作(将“yourappname”替换为应用程序的名称以获得正确的db表):


现在,在对数据库的一次查询中,每篇文章都将有一个
投票总数
,以及
令人敬畏的总数
有用的总数
。比ORM更难看一点,但仍然非常可读(这就是总和聚合的工作原理)。你仍然需要给每一类投票一次初始投票,以通过那些没有出现错误的投票。

Hmm,这会返回一些奇怪的东西,比如3,1,1,1,1,3,1,3,3,3,3,3,3,3,3,1,3,“…(剩余的元素被截断)…。]我想你误解了这个问题。你只是在排列投票名单,并说出名字是投哪一票。我想要的系统是按投票总数的顺序列出帖子(如我的回答所示)。显然我不明白这一点。但如果你已经提供了一个好答案:)和一个好答案,非常好的解释!哇,谢谢,这是一个很好的解决方案-我应该感到惭愧,我不知道总和聚合函数的存在。顺便说一句,是否有任何方式来过滤总投票数?我的意思是,在实际的项目中,我有不同类型的投票(例如,“awesomness”和“Usability”),我是否可以以某种方式过滤只按特定投票类型排序的相关投票,下面是一个在额外子句中使用SQL SELECT语句仅过滤一种投票类型的示例。非常感谢,你是我的救星:)我想,我应该学习SQL,因为ORM在某些情况下是不够的。@Data贪婪:很高兴得到了大家的帮助。这是django中非常罕见的一种情况,在这种情况下,了解一点SQL有助于超越ORM(并且SQL相当简单且可读)。django文档中也对其进行了详细的记录,参见第二个示例(唯一的区别是它们使用COUNT而不是SUM作为聚合,并且在where子句中没有and):仅供参考,
SUM()
的默认值是开放的。
>>> [(p.name, p.vote_total) for p in
     Post.objects.annotate(vote_total=Sum('vote__value')).order_by('-vote_total')]
[(u'post2', 4), (u'post1', 0), (u'post4', -1), (u'post3', -2)]
select_dict = dict(vote_total = "SELECT SUM(value) FROM yourappname_vote WHERE yourappname_vote.post_id = yourappname_post.id",
                   awesome_total = "SELECT SUM(value) FROM yourappname_vote WHERE yourappname_vote.post_id = yourappname_post.id AND yourappname_vote.type = 'AW' ",
                   useful_total = "SELECT SUM(value) FROM yourappname_vote WHERE yourappname_vote.post_id = yourappname_post.id AND yourappname_vote.type = 'US' ",)

posts = Post.objects.all().extra(select = select_dict).order_by('-vote_total')

>>> [(p.name, p.vote_total, p.awesome_total, p.useful_total) for p in posts]
[(u'post2', 4, 2, 2),
 (u'post1', 0, 0, 0),
 (u'post4', -1, -1, 0),
 (u'post3', -2, -2, 0)]