如何在order_by之后获取结果在列表中的位置?

Bob*_*Bob 7 python sql django rank

我正在尝试找到一种有效的方法来查找数据库中与其得分相关的对象的等级.我天真的解决方案看起来像这样:

rank = 0
for q in Model.objects.all().order_by('score'):
  if q.name == 'searching_for_this'
    return rank
  rank += 1
Run Code Online (Sandbox Code Playgroud)

应该可以使用order_by让数据库进行过滤:

Model.objects.all().ORDER_BY( '得分').过滤器(名称= 'searching_for_this')

但似乎没有办法在过滤器之后检索order_by步骤的索引.

有一个更好的方法吗?(使用python/django和/或原始SQL.)

我的下一个想法是在插入时预先计算排名,但这看起来很混乱.

Lud*_*mer 9

我不认为你可以使用Django ORM在一个数据库查询中执行此操作.但如果它不困扰你,我会在模型上创建一个自定义方法:

from django.db.models import Count

class Model(models.Model):
    score = models.IntegerField()
    ...

    def ranking(self):
        aggregate = Model.objects.filter(score__lt=self.score).aggregate(ranking=Count('score'))
        return aggregate['ranking'] + 1
Run Code Online (Sandbox Code Playgroud)

然后,您可以在任何地方使用"排名",就好像它是一个普通字段:

print Model.objects.get(pk=1).ranking
Run Code Online (Sandbox Code Playgroud)

  • 这应该是计算上昂贵的,因为它将运行`Model.objects.all()`中每行的排名聚合查询 (2认同)

Car*_*arl 5

使用Django 2.0中新Window函数,您可以像这样编写它...

from django.db.models import Sum, F
from django.db.models.expressions import Window
from django.db.models.functions import Rank

Model.objects.filter(name='searching_for_this').annotate(
            rank=Window(
                expression=Rank(),
                order_by=F('score').desc()
            ),
        )
Run Code Online (Sandbox Code Playgroud)

  • 这很棒,我唯一的问题是当我在查询集之后进行更多过滤时,它不会保持排名。就像我得到所有结果对它们进行排名一样,然后按用户名进行过滤,结果会根据较小的查询集而不是整个查询集进行排名。 (2认同)