Упорядочивание и ранжирование QuerySet в Django на основе существующих данных полей модели, ограниченное только первыми несколькими рангами?
У меня некоторые проблемы с выражениями Window() и Rank() для многоступенчатого ранжирования наборов QuerySets для спортивной симуляции, которую я создаю.
У меня есть три основные модели: Команда, Дивизион и Конференция. Вот их урезанная версия для иллюстрации их отношений друг с другом.
class Conference(models.Model):
name = models.CharField(max_length=200)
class Division(models.Model):
name = models.CharField(max_length=200)
conference = models.ForeignKey(
Conference, on_delete=models.CASCADE,
related_name='divisions'
)
class Team(models.Model):
division = models.ForeignKey(
Division, on_delete=models.CASCADE,
related_name='teams',
)
Я создаю рейтинги для каждой команды в их соответствующих дивизионах и конференциях на основе их TeamStanding в начале каждой недели (победы, поражения и т.д.). Рейтинги будут сохраняться в экземпляре TeamRanking (их пронумерованные места в дивизионе 1-4, конференции 1-16 и лиге 1-32), который имеет связь OneToOne с TeamStanding (по одному на команду, в неделю).
Уменьшенная версия вышеуказанных моделей, а также:
class TeamStanding(models.Model):
team = models.ForeignKey(
Team, on_delete=models.CASCADE,
related_name='team_standings',
)
# All the standing data fields
class TeamRanking(models.Model):
standing = models.OneToOneField(
TeamStanding, related_name='ranking',
on_delete=models.CASCADE,
)
# All the rankings fields
Вот как в настоящее время рассчитывается рейтинг дивизионов:
division_rank_qs = TeamStanding.objects.filter(
team__division__exact=division
).annotate(
rank=Window(
expression=Rank(),
order_by=[
F('wins').desc(), F('losses'),
F('points_for').desc(),
F('points_against')
],
)
)
Затем, чтобы получить доступ к рангам:
for ranked_div_standing in division_rank_qs:
rank = ranked_div_standing.rank
# Create TeamRanking instance
Теперь это отлично работает для основных расчетов рейтинга дивизионов. Проблема, с которой я сталкиваюсь, возникает при расчете рейтинга конференций, поскольку он в некоторой степени зависит от рейтинга дивизионов. Есть 4 дивизиона на конференцию и 4 команды на дивизион.
Каждая команда с 1-м местом в своем дивизионе должна быть в топ-4 рейтинга конференции, несмотря ни на что, но занимать 1-4 места на основе критериев упорядочивания с учетом ТОЛЬКО этих 3 других команд-лидеров дивизиона. Затем остальные 13 команд в конференции будут использовать те же критерии упорядочения, но ИСКЛЮЧАЯ 4 лучшие команды, которые были упорядочены отдельно. Таким образом, два совершенно разных порядка, основанных на отсечении между 4 и 5 местом.
Вот что я смог придумать на данный момент. Я использую уже сохраненный TeamRanking для дивизиона при упорядочивании, но проблема в том, что я не могу ограничить его только поиском рейтинга #1 и перестать использовать его после упорядочивания первых 4 лидеров конференций.
conference_rank_qs = TeamStanding.objects.filter(
team__division__conference__exact=conference
).annotate(
rank=Window(
expression=Rank(),
order_by=[
F('ranking__division_ranking'),
F('wins').desc(), F('losses'),
F('points_for').desc(),
F('points_against')
],
)
)
Есть ли способ достичь того, что я пытаюсь сделать, используя выражения Window() с Rank()? Я искал далеко и широко и не смог найти никаких других вопросов для моего случая использования.
Если вам нужна дополнительная информация, пожалуйста, сообщите мне об этом в комментариях. Спасибо.