【问题标题】:how to sort by a computed value in django如何在 django 中按计算值排序
【发布时间】:2010-10-30 04:10:19
【问题描述】:

嘿,我想根据 django 中的计算值对对象进行排序...我该怎么做?

这是一个基于堆栈溢出的示例用户配置文件模型,它解释了我的困境:

class Profile(models.Model):
    user = models.ForeignKey(User)

    def get_reputation():
        ... 
        return reputation
    reputation = property(get_reputation)

所以,假设我想按声誉对用户进行排序。我怎么做?我知道你不能这样做:

Profile.objects.order_by("-reputation")

感谢大家的帮助:)

【问题讨论】:

    标签: python django web-applications sorting django-models


    【解决方案1】:

    由于您的计算代码仅存在于 Python 中,因此您也必须在 Python 中执行排序:

    sorted (Profile.objects.all (), key = lambda p: p.reputation)
    

    【讨论】:

    • 嘿,这是我提出的问题的答案,但我接受了另一个问题,因为它解决了我遇到的问题......特别是 S.Lott 的评论。我升级了你的答案:)
    • 有没有办法让它返回一个查询集而不是一个常规的 python 列表(或将一个列表转换为一个查询集)?
    • 在评论中问这个问题似乎有点沉重,所以我把它移到了它自己的问题上:stackoverflow.com/questions/1058135/…
    【解决方案2】:

    从 Django-1.8 开始,只要计算值可以在 SQL 中呈现,就可以使用 query expressions 对 QuerySet 进行排序。您还可以将annotations 用于模型作为order_by 术语。

    from django.db.models import F
    Profile.objects.annotate(reputation=(F('<field>') + ...)).order_by("-reputation")
    

    +-*/** 等基本操作可以与 F() 一起使用。除此之外还有CountAvgMax、...等其他几个函数。

    链接:

    另请参阅此 SO Q&A:Order a QuerySet by aggregate field value

    【讨论】:

      【解决方案3】:

      如果您需要在数据库中进行排序(因为您有很多记录,并且需要对它们进行分页),唯一真正的选择是将信誉转换为非规范化字段(例如在覆盖的 save() 中更新模型上的方法)。

      【讨论】:

      • 我决定使用 post-save 信号而不是覆盖 save()... 这种方法有什么我应该知道的潜在问题吗?
      • 如果你想使用信号,我推荐 pre_save 而不是 post_save。要使用 post_save 使非规范化字段保持最新,意味着您必须执行两个 UPDATE 查询,其中一个就足够了。
      • @Carl Meyer 谢谢卡尔...我实际上正在更新与正在保存的模型不同的模型,但是谢谢...我认为经验法则是使用保存后更新与您保存的型号不同,如果是相同型号,请预先保存,不是吗?
      • @Jim Robert 当然,在这种情况下,您希望 post_save 确保仅在模型成功保存时才进行更新。
      猜你喜欢
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多