从方法订购

发布于 2024-10-04 10:20:57 字数 536 浏览 0 评论 0原文

大家好,我有一个像这样的简单模型

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')

编辑

我目前不在我的开发系统附近,所以语法可能有点不对。

Hay all, i have a simple model like this

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

With the view i can do things like

article_votes = article.votes

Am i able to order by the votes function? Something like

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

EDIT

I'm not near my dev system at the moment, so the syntax might be a little off.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

醉城メ夜风 2024-10-11 10:20:57

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

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

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

如果您无论如何都要检索所有文章,那么此解决方案没有任何缺点。另一方面,如果您只想要投票数最高的 10 篇文章,那么您将从数据库中提取所有文章,而不是让数据库进行排序,并且只返回前 10 篇文章。与纯 SQL 解决方案相比,这从数据库中检索更多的数据。

You can sort the list after the query returns the results:

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

sorted takes a list and sorts it. You can provide a custom function that takes an element and returns the value to use when comparing elements. lambda a: a.votes() is an anonymous function that takes an article and returns the number of votes on the article.

If you are going to retrieve all the articles anyway, there's no downside to this solution. On the other hand, if you wanted only the top 10 articles by votes, then you're pulling all the articles from the db instead of letting the db do the sort, and only returning the top ten. Compared to a pure SQL solution, this is retrieving much more data from the database.

自找没趣 2024-10-11 10:20:57

这是 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
""")

- 但我不确定双连接在您的情况下是否是一个好主意。另外,我不确定是否需要所有这些 DISCTINCT。这个查询很可能可以用更好的方式重写,但我目前没有想法。

This is a faster version of what Ned Batchelder suggested - as it does the counting in the database:

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

You can also do this completely inside the database:

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
""")

-- but I'm not sure if the double join is a good idea in your case. Also, I'm not sure if all those DISCTINCTs are needed. It's quite likely that this query can be rewritten in some better way, but I don't have an idea at the moment..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文