2009-05-19 12 views
24

¿Cómo se define un pedido específico en Django QuerySet s?Pedidos personalizados en Django

Específicamente, si tengo una QuerySet así: ['a10', 'a1', 'a2'].

orden regular (usando Whatever.objects.order_by('someField')) me dará ['a1', 'a10', 'a2'], mientras que yo estoy buscando: ['a1', 'a2', 'a10'].

¿Cuál es la forma correcta de definir mi propia técnica de ordenamiento?

Respuesta

39

Por lo que sé, no hay forma de especificar el orden en el lado de la base de datos de esta manera, ya que también sería específico del back-end. Es posible que desee recurrir a la buena clasificación Python pasada de moda:

class Foo(models.Model): 
    name = models.CharField(max_length=128) 

Foo.objects.create(name='a10') 
Foo.objects.create(name='a1') 
Foo.objects.create(name='a2') 

ordered = sorted(Foo.objects.all(), key=lambda n: (n[0], int(n[1:]))) 
print ordered # yields a1, a2, 10 

Si ves que necesitas este tipo de clasificación mucho, lo recomiendo hacer una subclase personalizada models.Manager para su modelo que realiza el pedido. Algo como:

class FooManager(models.Manager): 
    def in_a_number_order(self, *args, **kwargs): 
     qs = self.get_query_set().filter(*args, **kwargs) 
     return sorted(qs, key=lambda n: (n[0], int(n[1:]))) 

class Foo(models.Model): 
    ... as before ... 
    objects = FooManager() 

print Foo.objects.in_a_number_order() 
print Foo.objects.in_a_number_order(id__in=[5, 4, 3]) # or any filtering expression 
+0

el clavo! Maravillosa respuesta, gracias! –

+2

Recibo este error al intentar este método: \t El objeto 'Modelo' no se puede descomponer – ninja123

+0

¿'sorted' devuelve un conjunto de interrogación? Dado que se aprobó un conjunto de preguntas, creo que sí, pero creo que también se puede convertir en una lista o algo internamente para ordenar, luego * se devuelve *. –

0

Depende de dónde desee usarlo.

Si desea utilizarlo en sus propias plantillas, le sugiero que escriba una plantilla-etiqueta, que hará el pedido para usted En ella, podría utilizar cualquier algoritmo de clasificación que desee utilizar.

En administrador me encargo de clasificación mediante la ampliación de las plantillas para mis necesidades y la carga de una plantilla de etiqueta como se describe anteriormente

25

@ respuesta de Jarret (hacer la clase en Python) funciona muy bien para los casos simples. Tan pronto como tenga una tabla grande y quiera, por ejemplo, extraer solo la primera página de resultados ordenados de cierta manera, este enfoque se interrumpe (tiene que extraer cada fila de la base de datos antes de poder hacer la clasificación). En ese punto buscaría agregar un campo de "clasificación" desnormalizado que rellenarías desde el campo "nombre" en el momento del ahorro, que puedes ordenar en el nivel de base de datos de la forma habitual.

+2

+1 para abordar los problemas relacionados con el rendimiento; de hecho, su sugerencia es una que hemos utilizado en algunos de nuestros datos que se utilizan para informes, en un entorno independiente de DB, y tenemos decenas de millones de filas, por lo que puedo confirmar que funciona bien. . –

0

Si tiene grandes conjuntos de datos y utilizar, además, un backend SOLR (por ejemplo, con el pajar):

Uso solr.ICUCollationField con la opción numeric=true como tipo para los campos de clasificación. Esto ordenará según el idioma y, si hay números, clasificará la parte del número de acuerdo con las reglas numéricas en lugar de ordenar las cuerdas.

Ver: https://cwiki.apache.org/confluence/display/solr/Language+Analysis#LanguageAnalysis-UnicodeCollation http://www.solr-start.com/javadoc/solr-lucene/org/apache/solr/schema/ICUCollationField.html

Cuestiones relacionadas