Создание системы рейтинга на Джанго - PullRequest
0 голосов
/ 24 мая 2019

У меня есть футбольное приложение Django со следующими моделями, и я хочу создать набор запросов (или что-то еще) для построения таблицы «рейтинга» на моем шаблоне (передать как контекст):

  • Round (номер раунда, имя раунда)
  • Игра (раунд, команда1, команда2, цели, ошибки)
  • Команда (имя)
  • Игрок (имя, команда)
  • Гол (игра, игрок)
  • Ошибка (игра, игрок)

Имея эти модели с этими полями, как я могу построить таблицу ранжирования со следующей информацией?

Команда | Побед | Потери | Сыграно игр

1 Ответ

0 голосов
/ 24 мая 2019

Структура вашей модели данных делает некоторые вещи неинтуитивными, поэтому, если у вас есть гибкость, вы можете рассмотреть возможность изменения.

Например, если вы хотите получить список игр и знать кто выиграл игру это не тривиально, потому что в игровом столе нет колонки для команды-победителя или информации о том, сколько голов забила каждая команда.Вместо этого вы должны присоединиться к целям и игрокам, а затем игрокам команд.(Огромное предостережение о том, что я не могу протестировать этот код, и он достаточно сложен, чтобы в нем могли быть ошибки.)

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 (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, который является идентификатором команды-победителя, является денормализацией, которая делает все вышеперечисленное намного проще.Отношение Game и Team ко многим (даже если может быть только 2 команды) также упростит ситуацию.

...