You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Django的游戏排名表:如何实现排名功能?

实现Django排名表的自动排名功能

方法一:保存时自动更新数据库中的排名

当用户的胜负数据变动时,自动重新计算所有用户的排名并更新rank字段,适合数据量不大的场景。

修改模型的save方法:

from django.db.models import F

class BeerPongRankingTable(models.Model):
    rank = models.IntegerField(default=0, null=False)
    username = models.CharField(max_length=30, default='', null=False)
    wins = models.IntegerField(default=0, null=False)
    games = models.IntegerField(default=0, null=False)
    created_at = models.DateField(default=date.today)

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        # 按胜场降序、总场次降序排序(胜场相同则总场次多的排前面)
        ranked_users = BeerPongRankingTable.objects.all().order_by('-wins', '-games')
        # 批量更新排名,减少数据库操作
        update_list = []
        for index, user in enumerate(ranked_users, start=1):
            if user.rank != index:
                user.rank = index
                update_list.append(user)
        BeerPongRankingTable.objects.bulk_update(update_list, ['rank'])

方法二:查询时动态计算排名(不修改数据库)

无需改动数据库,在查询阶段为每个用户添加临时排名字段,适合数据量较大的场景。

视图层处理

from django.shortcuts import render
from .models import BeerPongRankingTable

def ranking_table(request):
    # 按自定义规则排序
    users = BeerPongRankingTable.objects.all().order_by('-wins', '-games')
    # 手动为每个用户添加排名属性
    for rank, user in enumerate(users, start=1):
        user.dynamic_rank = rank
    return render(request, 'ranking.html', {'users': users})

模板层展示

<table>
    <thead>
        <tr>
            <th>排名</th>
            <th>用户名</th>
            <th>胜场</th>
            <th>总场次</th>
        </tr>
    </thead>
    <tbody>
        {% for user in users %}
        <tr>
            <td>{{ user.dynamic_rank }}</td>
            <td>{{ user.username }}</td>
            <td>{{ user.wins }}</td>
            <td>{{ user.games }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>

方法三:用数据库窗口函数计算排名(高效推荐)

利用Django的窗口函数在数据库层面直接计算排名,性能最优,还能轻松处理并列排名场景。

视图层实现

from django.db.models import F, Window
from django.db.models.functions import RowNumber, Rank
from .models import BeerPongRankingTable

def ranking_table(request):
    # 普通排名(无并列,每个用户排名唯一)
    users = BeerPongRankingTable.objects.annotate(
        dynamic_rank=Window(
            expression=RowNumber(),
            order_by=F('wins').desc()
        )
    ).order_by('dynamic_rank')

    # 并列排名(胜场相同则排名一致)
    # users = BeerPongRankingTable.objects.annotate(
    #     dynamic_rank=Window(
    #         expression=Rank(),
    #         order_by=F('wins').desc()
    #     )
    # ).order_by('dynamic_rank')
    
    return render(request, 'ranking.html', {'users': users})

模板层展示

和方法二一致,直接使用{{ user.dynamic_rank }}展示排名即可。

补充说明

  • 如果用方法二或三,建议移除模型中的rank字段,避免数据混淆。
  • 可根据需求调整排序规则,比如按胜率排序:order_by(F('wins')/F('games').desc(), '-wins'),注意处理games=0的异常情况。
  • 批量导入数据时,方法一需要手动触发一次排名更新,确保数据正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:30:41