Упорядочивание и ранжирование 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()? Я искал далеко и широко и не смог найти никаких других вопросов для моего случая использования.

Если вам нужна дополнительная информация, пожалуйста, сообщите мне об этом в комментариях. Спасибо.

Вернуться на верх