Infelizmente, não é uma operação possível, pois (para mim) o postgresql
WHERE
A operação (filtrar/excluir) restringe as linhas antes que as funções de agregação possam trabalhar nelas. A única solução que encontrei é simplesmente calcular a classificação para todas as
Person
com um conjunto de consultas separado e, em seguida, anotar seu conjunto de consultas com esses resultados. Esta resposta (veja o método aprimorado) explica como "anotar um conjunto de consultas com dados preparados externamente em um dict".
Aqui está a implementação que fiz para seus modelos:
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')))
Eu testei com Django 2.1.3 e Postgresql 10.5, então o código pode mudar levemente para você.
Sinta-se à vontade para compartilhar uma versão compatível com o Django 1.11!