За съжаление това не е възможна операция, тъй като (за мен) postgresql WHERE
операция (филтриране/изключване) стеснява редовете, преди функциите за агрегиране да могат да работят върху тях.
Единственото решение, което намерих, е просто да изчисля класирането за всички Person
с отделен набор от заявки и след това, за да анотирате набора от заявки с тези резултати.
Този отговор (вижте подобрения метод) обяснява как да "анотирате набор от заявки с външно подготвени данни в dict".
Ето изпълнението, което направих за вашите модели:
class PersonQuerySet(models.QuerySet):
def total_scores(self):
# compute the global ranking
ranks = (Person.objects
.annotate(total_score=models.Sum('session__gamesession__score'))
.annotate(rank=models.Window(expression=DenseRank(),
order_by=models.F('total_score').decs()))
.values('pk', 'rank'))
# extract and put ranks in a dict
rank_dict = dict((e['pk'], e['rank']) for e in ranks)
# create `WHEN` conditions for mapping filtered Persons to their Rank
whens = [models.When(pk=pk, then=rank) for pk, rank in rank_dict.items()]
# build the query
return (self.annotate(rank=models.Case(*whens, default=0,
output_field=models.IntegerField()))
.annotate(total_score=models.Sum('session__gamesession__score')))
Тествах го с Django 2.1.3 и Postgresql 10.5, така че кодът може леко да се промени за вас.
Чувствайте се свободни да споделите версия, съвместима с Django 1.11!