Un QuerySet por valor de campo agregado

Digamos que tengo el siguiente modelo:

class Contest: title = models.CharField( max_length = 200 ) description = models.TextField() class Image: title = models.CharField( max_length = 200 ) description = models.TextField() contest = models.ForeignKey( Contest ) user = models.ForeignKey( User ) def score( self ): return self.vote_set.all().aggregate( models.Sum( 'value' ) )[ 'value__sum' ] class Vote: value = models.SmallIntegerField() user = models.ForeignKey( User ) image = models.ForeignKey( Image ) 

Los usuarios de un sitio pueden contribuir con sus imágenes a varios concursos. Luego otros usuarios pueden votar hacia arriba o hacia abajo.

Todo funciona bien, pero ahora quiero mostrar una página en la que los usuarios pueden ver todas las contribuciones a un concurso determinado. Las imágenes se ordenarán por su puntuación. Por eso he intentado lo siguiente:

 Contest.objects.get( pk = id ).image_set.order_by( 'score' ) 

Como temía, no funciona ya que 'score' no es un campo de base de datos que pueda usarse en las consultas.

Oh, por supuesto que me olvido del nuevo soporte de agregación en Django y su funcionalidad de annotate .

Así que la consulta puede verse así:

 Contest.objects.get(pk=id).image_set.annotate(score=Sum('vote__value')).order_by( 'score' ) 

Puedes escribir tu propio tipo en Python de manera muy simple.

 def getScore( anObject ): return anObject.score() objects= list(Contest.objects.get( pk = id ).image_set) objects.sort( key=getScore ) 

Esto funciona bien porque ordenamos la lista, que le proporcionaremos a la plantilla.

El order_by nivel de order_by no puede ordenar el conjunto de consultas por el método python del modelo.

La solución es introducir el campo de score en el modelo de Image y recalcularlo en cada actualización de Vote . Algún tipo de desnormalización. Cuando se pueda ordenar por ello.