【问题标题】:Building a ranking system on Django在 Django 上构建排名系统
【发布时间】:2019-10-10 13:33:55
【问题描述】:

我有一个带有以下模型的 Django 足球应用程序,我想创建一个查询集(或其他东西)以在我的模板上构建一个“排名”表(作为上下文传递):

  • 圆(round_number,round_name)
  • 比赛(回合、团队 1、团队 2、进球、失误)
  • 团队(名称)
  • 球员(姓名、球队)
  • 目标(游戏、玩家)
  • 故障(游戏、玩家)

拥有这些具有这些字段的模型,我如何构建包含以下信息的排名表?

团队 |获胜 |损失 |玩过的游戏

【问题讨论】:

  • 如果你能分享你迄今为止尝试过的东西会更好。所以这里的人可以帮助您找到最佳方法。
  • 问题是我什至不知道从哪里开始,我不知道我是否需要创建另一个模型以便为每个团队得分输入条目,或者我是否可以计算它用一个方法和类似的东西

标签: django django-models django-views


【解决方案1】:

您的数据模型的结构使某些事情变得不直观,因此如果您在这方面具有灵活性,您可能需要考虑进行更改。

例如,如果您想获取游戏列表并了解谁赢得了游戏,这并非易事,因为游戏表没有获胜球队的列,或者有关如何赢得比赛的信息每支球队进了很多球。相反,你必须加入目标,加入球员,然后加入球员队伍。 (请注意,我无法测试此代码,而且它足够复杂,可能会出现错误。)

from django.db.models import Count, Q, F, Case, When

games = Game.objects.annotate(
    team1_goal_count=Count('goals', filter=Q(goals__player__team=F('team1'), distinct=True),
    team2_goal_count=Count('goals', filter=Q(goals__player__team=F('team2'), distinct=True),
    result=Case(When(Q(team1_goal_count__gt=team2_goal_count), then=F('team1')),
                When(Q(team2_goal_count__gt=team1_goal_count), then=F('team2')),
                default=None)
)

上面将为您提供一个查询集,其中包含每个团队的目标计数和result 列中获胜团队的 ID(null 在平局的情况下)

如果你想得到一个按胜率排序的球队名单,他们的赢/输/平记录,你必须加入比赛并类似地计算分数(注意,这太复杂了,我不知道如果它甚至像我写的那样工作):

from django.db.models import Subquery, OuterRef
# Use the `games` query from above
scored_games_1 = games.filter(team1_id=OuterRef('pk'))
scored_games_2 = games.filter(team2_id=OuterRef('pk'))

# Need to group by the OuterRef('pk')
scored_games_1 = scored_games_1.values('team1')
scored_games_2 = scored_games_2.values('team2')

# Annotate the counts and select on that column
scored_games_1 = scored_games_1.annotate(count=Count('pk')).values('count')
scored_games_2 = scored_games_2.annotate(count=Count('pk')).values('count')

won_q = Q(result=F('pk'))
lost_q = Q(result__isnull=False) & ~Q(result=F('pk'))
tied_q = Q(result__isnull=True)
teams = Team.objects.annotate(
    games_won=Subquery(scored_games_1.filter(won_q)) + Subquery(scored_games_2.filter(won_q)),
    games_lost=Subquery(scored_games_1.filter(lost_q)) + Subquery(scored_games_2.filter(lost_q)),
    games_tied=Subquery(scored_games_1.filter(tied_q) + Subquery(scored_games_2.filter(tied_q)),
    winning_percentage=F('games_won') / (F('games_won') + F('games_lost') + F('games_tied'))
).order_by('-winning_percentage')

Game 中包含一个列,即获胜团队的 id,这是一种非规范化,使上述所有内容变得如此简单。使GameTeam 成为多对多关系(即使只能有2 个团队)也会使事情变得更容易。

【讨论】:

  • 非常感谢您的帮助,我确实可以灵活地更改我的模型,您能否更新您的答案并提供一些有关结构的建议?
  • 嗯,我的最后一段有两个建议,但诚实的事实是,从长远来看,不可能准确地说出正确的选择是什么。
猜你喜欢
  • 2012-06-11
  • 2012-07-06
  • 1970-01-01
  • 2020-07-28
  • 2018-08-05
  • 2012-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多