2009-05-30 17 views
5

Hola, quiero ordenar objetos en base a un valor calculado en django ... ¿cómo lo hago?cómo ordenar por un valor calculado en django

Aquí es un modelo de perfil de usuario de ejemplo basado en desbordamiento de pila que explica mi situación:

class Profile(models.Model): 
    user = models.ForeignKey(User) 

    def get_reputation(): 
     ... 
     return reputation 
    reputation = property(get_reputation) 

Por lo tanto, decir que quiero ordenar los usuarios por su reputación. ¿Cómo puedo hacer eso? Sé que no se puede simplemente hacer esto:

Profile.objects.order_by("-reputation") 

Gracias por su ayuda a todos :)

Respuesta

3

Si es necesario realizar la ordenación en la base de datos (porque tiene un montón de registros, y la necesidad de, por ejemplo, paginate ellos), la única opción real es convertir la reputación en un campo sin normalizar (por ejemplo, actualizada en una anulado save() método en el modelo).

+2

+1: simplemente anule guardar() para mantener este campo actualizado. –

+0

Decidí usar la señal de post-guardado en lugar de anular save() ... ¿hay posibles errores que deba conocer con ese enfoque? – Jiaaro

+0

Si quieres usar señales, te recomendaría pre_save en lugar de post_save. Mantener un campo desnormalizado actualizado con post_save significa que debe realizar dos consultas de actualización donde sería suficiente. –

16

Dado que existe el código de cálculo sólo dentro de Python, usted tiene que realizar la clasificación en Python, así:

sorted (Profile.objects.all(), key = lambda p: p.reputation) 
+0

hey, esta es la respuesta a la pregunta que hice, pero acepté la otra porque resolvió el problema que tengo ... específicamente el comentario de S.Lott. Sin embargo, modifiqué tu respuesta :) – Jiaaro

+0

¿hay alguna manera de hacer que esto devuelva un conjunto de consulta en lugar de una lista de python normal (o convertir una lista en un conjunto de consulta)? – Jiaaro

+0

Me parece un poco pesado preguntar en un comentario, así que lo moví a su propia pregunta: http://stackoverflow.com/questions/1058135/django-convert-a-list-back-to-a-queryset – Jiaaro

5

A partir de Django-1.8, es posible ordenar un QuerySet usando query expressions, siempre que el valor calculado se pueda representar en SQL. También puede usar annotations para el modelo como el término order_by.

from django.db.models import F 
Profile.objects.annotate(reputation=(F('<field>') + ...)).order_by("-reputation") 

operaciones básicas como +, -, *, / y ** se pueden utilizar con F(). Además hay varias otras funciones tales como Count, Avg, Max, ...

Enlaces:

Véase también este SO Q & A: Order a QuerySet by aggregate field value

Cuestiones relacionadas