You need to enable JavaScript to run this app. 如何基于Django查询集中Menu对象的得票数为其分配对应排名
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Django查询集中Menu对象的得票数为其分配对应排名

实现方案说明

首先明确:可以通过Django Query Expressions实现该需求,且该方案性能最优,排名逻辑直接在数据库侧执行,无需额外内存计算

方案1:使用Django窗口函数(推荐,Django 2.0+版本支持)

Django内置的Window表达式搭配排名函数,可以直接在查询时生成排名字段,支持两种常用排名规则:

  • DenseRank:同得分排名相同,排名序号连续不跳号(比如你示例中两个2票的菜单均为第2名,下一个1票的为第3名)
  • Rank:同得分排名相同,排名序号跳号(比如你示例中两个2票的菜单均为第2名,下一个1票的为第4名)

代码实现:

from django.db.models import Q, Window, DenseRank, F

# 生成带排名的查询集
qs = Menu.objects.filter(
    Q(created_at__date__iexact=todays_date)
).annotate(
    # 按得票数倒序计算密集排名
    rank=Window(
        expression=DenseRank(),
        order_by=F('votes').desc()
    )
).order_by('-votes', 'id')

查询返回的每个Menu对象会自动携带rank属性,序列化时直接把该字段加入序列化器即可直接返回带排名的结果。

方案2:Python内存层处理(兼容低版本Django,适合小数据量场景)

如果你的Django版本低于2.0,或者当日菜单数据量很小,可以直接在Python层遍历查询集分配排名:

qs = Menu.objects.filter(
    Q(created_at__date__iexact=todays_date)
).order_by('-votes', 'id')

current_rank = 1
prev_vote = None
same_count = 0
for menu in qs:
    if menu.votes != prev_vote:
        current_rank += same_count
        same_count = 0
    # 给对象动态绑定rank属性
    menu.rank = current_rank
    same_count += 1
    prev_vote = menu.votes

处理后的查询集对象同样携带rank属性,可直接序列化返回。

示例数据返回效果

按照上述方案处理后,你提供的示例数据会新增rank字段如下:

[
  {
    "id": 10,
    "file": "https://res.cloudinary.com/dw9bllelz/raw/upload/v1/media/menus/index_ah660c.jpeg",
    "restaurant": "Burger King",
    "votes": 10,
    "created_at": "2021-06-03T09:33:05.505482+03:00",
    "rank": 1
  },
  {
    "id": 9,
    "file": "https://res.cloudinary.com/dw9bllelz/raw/upload/v1/media/menus/index_ah660c.jpeg",
    "restaurant": "Texas Plates",
    "votes": 2,
    "created_at": "2021-06-03T09:33:05.505482+03:00",
    "rank": 2
  },
  {
    "id": 8,
    "file": "https://res.cloudinary.com/dw9bllelz/raw/upload/v1/media/menus/index_ah660c.jpeg",
    "restaurant": "Carlito Dishes",
    "votes": 2,
    "created_at": "2021-06-03T09:33:05.505482+03:00",
    "rank": 2
  },
  {
    "id": 7,
    "file": "https://res.cloudinary.com/dw9bllelz/raw/upload/v1/media/menus/index_ah660c.jpeg",
    "restaurant": "Kram Dishes",
    "votes": 1,
    "created_at": "2021-06-03T09:33:05.505482+03:00",
    "rank": 3
  }
]

内容的提问来源于stack exchange,提问作者Philip Mutua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 18:54:00