Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.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_Algorithm_Sorting - Fatal编程技术网

Python Django:将计算应用于查询集

Python Django:将计算应用于查询集,python,django,algorithm,sorting,Python,Django,Algorithm,Sorting,我有一个查询集,希望传递给通用视图进行分页: links = Link.objects.annotate(votes=Count('vote')).order_by('-created')[:300] 这是我的“热门”页面,其中列出了我最近提交的300份意见书(10页,每页30个链接)。现在,我想按照HackerNews使用的算法对该查询集进行排序: (p - 1) / (t + 2)^1.5 p = votes minus submitter's initial vote t = age o

我有一个查询集,希望传递给通用视图进行分页:

links = Link.objects.annotate(votes=Count('vote')).order_by('-created')[:300]
这是我的“热门”页面,其中列出了我最近提交的300份意见书(10页,每页30个链接)。现在,我想按照HackerNews使用的算法对该查询集进行排序:

(p - 1) / (t + 2)^1.5
p = votes minus submitter's initial vote
t = age of submission in hours
现在,因为在整个数据库中应用此算法将花费相当大的成本,我只满足于最后300次提交。我的网站不太可能成为下一个digg/reddit,因此,尽管可扩展性是一个加号,但它是必需的

我现在的问题是,如何迭代查询集并按照上述算法对其排序

有关更多信息,以下是我的适用车型:

class Link(models.Model):
    category = models.ForeignKey(Category, blank=False, default=1)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    url = models.URLField(max_length=1024, unique=True, verify_exists=True)
    name = models.CharField(max_length=512)

    def __unicode__(self):
        return u'%s (%s)' % (self.name, self.url)

class Vote(models.Model):
    link = models.ForeignKey(Link)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return u'%s vote for %s' % (self.user, self.link)
注:

  • 我没有“否决票”,所以只有投票行的存在才是特定用户投票或特定链接的指示器
  • 编辑

    我想我已经把事情复杂化了,找到了一段漂亮的小代码:

    links = Link.objects.annotate(votes=Count('vote')).order_by('-created')[:300]
    for link in links:
        link.popularity = ((link.votes - 1) / (2 + 2)**1.5)
    
    但就我的一生而言,我无法将其转化为我的模板:

    {% for link in object_list %}
        Popularity: {{ link.popularity }}
    {% endfor %}
    
    为什么它没有出现?我知道人气在起作用,因为:

    print 'LinkID: %s - Votes: %s - Popularity: %s' % (link.id, link.votes, link.popularity)
    

    返回我在控制台中期望的值。

    如果可能,您可以从查询集中创建一个值dict或值列表,并将排序算法应用于获取的dict(列表)。 看

    示例

    # select links
    links = Link.objects.annotate(votes=Count('vote')).order_by('-created')[:300]
    # make a values list:
    links = links.values_list('id', 'votes', 'created')
    # now sort 
    # TODO: you need to properly format your created date (x[2]) here
    list(links).sort(key = lambda x: (x[1] - 1) / (x[2] + 2)^1.5)
    
    其中,
    s
    应该从计算出的最高重要度开始排序,排在第一位,排在最后一位,如下所示:


    [(计算重要性,obj),(计算重要性,obj),…]

    虽然无法通过查询集进行计算,但我必须转换为排序列表

    links = Link.objects.select_related().annotate(votes=Count('vote'))
    for link in links:
        delta_in_hours = (int(datetime.now().strftime("%s")) - int(link.created.strftime("%s"))) / 3600
        link.popularity = ((link.votes - 1) / (delta_in_hours + 2)**1.5)
    
    links = sorted(links, key=lambda x: x.popularity, reverse=True)
    

    不是最优的,但它是有效的。我不能用我可爱的对象列表通用视图自动分页,不得不求助于手动操作,但这是一个公平的折衷方案,可以使用工作视图…

    麻烦您提供一个例子吗?可能会在每个
    投票
    值中添加1。我很难理解这个概念。谢谢你的例子!虽然
    'ValuesListQuerySet'对象没有属性“sort”
    我是否缺少导入?嗯,我想这是因为它不是一个完整的列表,为什么排序不是一个可用的选项。走近我想:
    keyrerror at/links/1
    HmmBut我会说我需要将我的QS传递给一个通用视图,所以我不确定将其转化为列表是最好的选项。因为我正在通过一个通用视图将这个计算出的列表传递给我的模板,我认为它需要保持QS。不要使用通用视图作为解决方案。编写自己的视图很容易,它在上下文中返回排序列表,我认为不需要对5项进行分页。也许还可以在数据库级别上使用
    raw()
    来实现这一点,从而使数据库计算流行度并按其排序。在数据库级别上进行此操作已被证明是。。。。困难。虽然人们通过使用.extra提供了这个问题的答案,但它们实际上似乎不起作用。raw()的工作原理与extra稍有不同,它返回纯SQL的查询集。我认为使用SQL会更快。哈哈,唉,我想我得去拿开发版了。
    links = Link.objects.select_related().annotate(votes=Count('vote'))
    for link in links:
        delta_in_hours = (int(datetime.now().strftime("%s")) - int(link.created.strftime("%s"))) / 3600
        link.popularity = ((link.votes - 1) / (delta_in_hours + 2)**1.5)
    
    links = sorted(links, key=lambda x: x.popularity, reverse=True)