Lamentablemente, no es una operación posible ya que (para mí) postgresql WHERE
La operación (filtrar/excluir) reduce las filas antes de que las funciones de agregación puedan trabajar en ellas.
La única solución que encontré es simplemente calcular la clasificación para todas las Person
con un conjunto de consultas separado y luego, para anotar su conjunto de consultas con estos resultados.
Esta respuesta (consulte el método mejorado) explica cómo "anotar un conjunto de consultas con datos preparados externamente en un dictado".
Aquí está la implementación que hice para sus 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')))
Lo probé con Django 2.1.3 y Postgresql 10.5, por lo que el código puede cambiar ligeramente para usted.
¡Siéntase libre de compartir una versión compatible con Django 1.11!