从方法排序

2021-08-02 16:37:20 发布

您现在位置:Python中文网/ 问答频道 /正文

好吧,我有一个这样简单的模型

def Article(models.Model):
    upvotes = models.ManyToManyField(User, related_name='article_upvotes')
    downvotes = models.ManyToManyField(User, related_name='article_downvotes')

    def votes(self):
        return self.upvotes - self.downvotes

有了这样的观点我可以做

article_votes = article.votes

我能通过投票功能订购吗?像这样的

article = Article.objects.order_by('votes')

编辑

我现在不在我的开发系统附近,所以语法可能有点错误。你知道吗

2条回答
网友
1楼 ·

您可以在查询返回结果后对列表进行排序:

article_votes = sorted(article.votes, key=lambda a: a.votes())

sorted获取一个列表并对其排序。您可以提供一个自定义函数,该函数接受一个元素并返回在比较元素时要使用的值。lambda a: a.votes()是一个匿名函数,它接受一篇文章并返回该文章的投票数。你知道吗

如果你要检索所有的文章,这个解决方案没有坏处。另一方面,如果你只想投票选出前十名的文章,那么你就把所有的文章都从db中拉出来,而不是让db做排序,只返回前十名。与纯SQL解决方案相比,这是从数据库中检索更多的数据。你知道吗

网友
2楼 ·

这是Ned Batchelder建议的一个更快的版本,因为它在数据库中进行计数:

articles = list(Article.objects.annotate(upvote_num=models.Count('upvotes'), downvote_num=models.Count('downvotes')))
articles.sort(key=lambda a: a.upvotes - a.downvotes)

也可以完全在数据库中执行此操作:

articles = Article.objects.raw("""
    SELECT DISTINCT id from articles_article,
    COUNT(DISTINCT upv) AS num_upvotes,
    COUNT(DISTINCT downv) AS num_downvotes,
    (num_upvotes - num_downvotes) AS score

    INNER JOIN [article_user_upvotes_m2m_table_name] AS upv
    ON upv.article_id = id

    INNER JOIN [article_user_downvotes_m2m_table_name] AS downv
    ON downv.article_id = id

    GROUP BY id
    ORDER BY score
""")

但我不确定双重连接对你来说是不是个好主意。另外,我不确定是否需要所有这些显示器。很可能这个查询可以用更好的方式重写,但我现在还不知道。。你知道吗

相关问题