2011-08-23 14 views
31

Pregunta breve
¿Cuál es el orden predeterminado de una lista devuelta por una llamada de filtro Django cuando se conecta a una base de datos PostgreSQL?¿Cuál es el orden predeterminado de una lista devuelta por una llamada de filtro de Django?

Antecedentes
Por mi propia admisión, que tenía hizo una mala suposición en la capa de aplicación en el que el orden en el que se devuelve una lista será constante, es decir, sin el uso de 'order_by'. La lista de elementos que estaba consultando no está en orden alfabético ni en ninguna otra orden deliberada. Se pensó que permanecería en el mismo orden en que se agregaron a la base de datos.

Esta suposición se cumple para cientos de consultas, pero mi aplicación informó de un error cuando la orden cambió sin saberlo. Que yo sepa, ninguno de estos registros fue tocado durante este tiempo ya que soy la única persona que mantiene el DB. Para aumentar la confusión, al ejecutar la aplicación Django en Mac OS X, todavía funcionaba como se esperaba, pero en Win XP, cambió el orden. (Tenga en cuenta que los cientos de consultas mencionadas estaban en Win XP).

Cualquier información sobre esto sería útil ya que no pude encontrar nada en la documentación de Django o PostgreSQL que explicara las diferencias en los sistemas operativos.

Ejemplo de llamada

required_tests = Card_Test.objects.using(get_database()).filter(name__icontains=key) 

EDITAR
Después de hablar con la actualidad de algunos de mis colega, que había llegado con la misma respuesta que Björn Lindqvist.

Mirando hacia atrás, definitivamente entiendo por qué esto se hace tan a menudo. Uno de los beneficios de utilizar un ORM Django, sqlalchemy, o lo que sea, es que puede escribir comandos sin tener que conocer o comprender (en detalle) la base de datos a la que está conectado. Es cierto que he sido uno de estos usuarios. Sin embargo, por el otro lado de esto es que sin conocer la base de datos en detalle los errores de depuración como este son bastante problemáticos y potencialmente catastróficos.

Respuesta

50

Hay SIN ORDEN POR DEFECTO, un punto que no se puede enfatizar lo suficiente porque todos lo hacen mal.

Una tabla en una base de datos no es una tabla html común, es un conjunto desordenado de tuplas. Suele sorprender a los programadores que solo utilizan MySQL porque en esa base de datos particular el orden de las filas suele ser predecible debido a que no aprovecha algunas de las técnicas de optimización avanzadas. Por ejemplo, no es posible saber qué se devolverán filas, o su orden en cualquiera de las siguientes consultas:

select * from table limit 10 
select * from table limit 10 offset 10 
select * from table order by x limit 10 

En la última consulta, el orden sólo es predecible si todos los valores de la columna x son únicos . El RDBMS puede devolver cualquier fila en el orden que desee, siempre que satisfaga las condiciones de la instrucción select.

Aunque es posible añadir un orden predeterminado en el nivel de Django, que hace que se añada una cláusula ORDER BY a cada consulta no ordenada:

class Table(models.Model): 
    ... 
    class Meta: 
     ordering = ['name'] 

Tenga en cuenta que puede ser un lastre para el rendimiento, si por alguna razón por la que no necesita filas ordenadas.

+0

entrega firme agradable :) – kronosapiens

-1

Si desea se le restituyan en el orden en que se insertan:

Añadir lo siguiente a su modelo:

created = models.DateTimeField(auto_now_add=True, db_index=True) 
# last_modified = models.DateTimeField(auto_now=True, db_index=True) 

class Meta: 
    ordering = ['created',] 
    # ordering = ['-last_modified'] # sort last modified first 
+0

En lugar de modificar el modelo para añadir un nuevo campo, ¿por qué no simplemente ordenar por el id de auto incremento que tienen la mayoría de los modelos? No está sujeto a problemas de precisión (debe preocuparse por la granularidad de DateTimeField) o los cambios de tiempo del sistema los engañan. – aggieNick02

+0

Eso solo funciona si realmente está seguro de que las inserciones siempre están usando el autoincr. secuencia y nunca vuelven a usar identificadores no utilizados, volcados de otros DB o tablas que establecen un tiempo creado que no se reflejaría en el orden de la clave principal. No es transparente usar la ID cuando realmente desea ordenar por fecha, y a menudo realmente desea ordenar por last_modified, y la ID no ayudará en ese caso. – Risadinha

+0

Estoy de acuerdo en que hay algunos casos de esquina en los que es posible que desee hacer algo personalizado, pero de forma predeterminada, cada modelo obtiene una identificación de incremento automático y no hay reutilización de identificación no utilizada. Además, con DateTimeField, tiene un problema si dos modelos terminan con el mismo valor en su DateTimeField. Esto podría suceder en función de la precisión debida a la versión de django/backend de la base de datos. – aggieNick02

Cuestiones relacionadas