【问题标题】:Django order by calculated valueDjango按计算值排序
【发布时间】:2021-02-22 09:07:39
【问题描述】:

我有 2 个模型,

Player
- id: int
- name: string

Ball
- type: string
- player_id: int

基本上这个想法是一个球员可以拥有一定数量的球。 ball.type 中球的类型可以是 BIG 或 SMALL(存储为字符串值)

现在我想根据计算出的声望对玩家进行排序。声望公式如下

reputation = No of Big balls x 10 + No of Small balls

所以例如一个大球和一个小球的球员的声誉将是 11。

有人可以就如何根据此声誉对用户进行排序提供一个想法吗?感谢您的帮助。

【问题讨论】:

    标签: python django django-orm


    【解决方案1】:

    您可以尝试注释并使用它来订购:

    from django.db.models import Count, Q, Value
    
    Player.objects.all().annotate(reputation=Count('ball', filter=Q(ball__type="BIG")) * Value(10) + Count('ball', filter=Q(ball__type="SMALL"))).order_by('reputation')
    

    【讨论】:

    • 非常感谢。我有个主意。实际上,我的声誉公式有点不准确。我们将如何解释上述代码中的小球数?谢谢
    • @Sagar 编辑了答案。如果需要,您也可以通过写~Q(.....) 来否定 Q 对象。
    【解决方案2】:

    您可以使用 Django Manager 类。考虑代码:

    class PlayerManager(models.Manager):
        def with_reputation(self):
            # using the formula from "Abdul Aziz Barkat"
            return self.annotate(reputation = Count('ball', filter=Q(ball__type="BIG")) * Value(10) + \
                                              Count('ball', filter=Q(ball__type="SMALL")))
    

    并且在您的 Players 模型中,您使用 with_reputation 生成一个带有信誉注释的查询集,您可以对其进行排序

    class Player(models):
         objects = PlayerManager()
    

    现在在您的代码中,您可以使用 Players.objects.with_reputation() 来获取一个查询集,并在每条记录中添加注释 reputation。然后你可以用它来做订购

    Players.objects.with_reputation().order_by('reputation')
    

    或:

    Players.objects.with_reputation().filter(name='Sam').ordere_by('reputation')
    

    您可以在此处阅读有关经理的更多信息: https://docs.djangoproject.com/en/3.1/topics/db/managers/

    【讨论】:

    • .order_by('reputation') 可以在with_reputation 内完成。如果您总是想要使用该排序,那么这样做可能是有意义的。此外,您无需将标准 objects Manager 替换为新的 - 您始终可以在 class Player 中同时包含 objects = Manager()pm = PlayerManager()
    猜你喜欢
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    相关资源
    最近更新 更多