2011-08-23 6 views
31

Breve domanda
Qual è l'ordine predefinito di un elenco restituito da una chiamata di filtro Django quando è collegato a un database PostgreSQL?Qual è l'ordine predefinito di un elenco restituito da una chiamata di filtro Django?

Sfondo
Con la mia stessa ammissione, ho avuto fatto una scarsa assunzione al livello di applicazione in quanto l'ordine in cui viene restituita una lista sarà costante, cioè senza l'utilizzo di 'order_by'. L'elenco degli elementi che stavo interrogando non è in ordine alfabetico o altro deliberato dell'ordine. Si è pensato di rimanere nello stesso ordine con cui sono stati aggiunti al database.

Questa ipotesi è valida per centinaia di query, ma un errore è stato segnalato dalla mia domanda quando l'ordine è cambiato inconsapevolmente. Per quanto ne so, nessuno di questi documenti è stato toccato durante questo periodo poiché sono l'unica persona che gestisce il DB. Per aggiungere confusione, quando si eseguiva l'app Django su Mac OS X, funzionava ancora come previsto, ma su Win XP, ha cambiato l'ordine. (Si noti che le centinaia di query menzionate erano su Win XP).

Qualsiasi intuizione sarebbe utile in quanto non sono riuscito a trovare nulla nella documentazione di Django o PostgreSQL che spiegasse le differenze nei sistemi operativi.

Esempio di chiamata

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

EDIT
Dopo aver parlato con oggi qualche mio collega, mi era venuto con la stessa risposta Björn Lindqvist.

Guardando indietro, ho sicuramente capito perché questo è fatto male così spesso. Uno dei vantaggi dell'uso di un ORM Django, di sqlalchemy o di qualsiasi altra cosa è che è possibile scrivere comandi senza dover conoscere o comprendere (in dettaglio) il database a cui è connesso. Devo ammettere che sono stato uno di questi utenti. Tuttavia sul lato opposto di questo è che senza conoscere il database in dettaglio errori di debug come questo sono abbastanza fastidiosi e potenzialmente catastrofici.

risposta

50

C'è NESSUN ORDINE PREDEFINITO, un punto che non può essere enfatizzato abbastanza perché tutti sbagliano.

Una tabella in un database non è un normale tabella html, è un insieme non ordinato di tuple. Sorprende spesso i programmatori utilizzati solo su MySQL perché in quel particolare database l'ordine delle righe è spesso prevedibile perché non sfrutta alcune tecniche di ottimizzazione avanzate. Ad esempio, non è possibile sapere quali righe saranno restituiti, o loro ordine in una qualsiasi delle seguenti domande:

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

Nell'ultimo interrogazione, l'ordine è prevedibile solo se tutti i valori nella colonna x sono unici . RDBMS è libero di restituire qualsiasi riga nell'ordine che preferisce purché soddisfi le condizioni dell'istruzione select.

Anche se si può aggiungere un ordinamento di default a livello Django, che induce a aggiungere una clausola ORDER BY per ogni query non ordinato:

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

Nota che potrebbe essere un freno prestazioni, se per qualche ragione per cui non hai bisogno di righe ordinate.

+0

Nizza consegna ferma :) – kronosapiens

-1

Se si desidera avere loro restituiti nell'ordine in cui sono stati inseriti:

Aggiungere il seguente al modello:

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

Invece di modificare il proprio modello per aggiungere un nuovo campo, perché non ordinare semplicemente dall'id auto-incrementante che la maggior parte dei modelli ha? Non è soggetto a problemi di precisione (devi preoccuparti di quanto sia granulare DateTimeField) o essere ingannato dalle modifiche all'ora del sistema. – aggieNick02

+0

Funziona solo se si è veramente sicuri che gli inserti utilizzino sempre l'auto-incr. sequenza e non stanno mai riutilizzando ID inutilizzati, dump da altri DB o tabelle che impostano un tempo creato che non si rifletterebbe nell'ordine della chiave primaria. Non è trasparente usare l'ID quando si vuole veramente ordinare per data - e spesso si vuole veramente ordinare per last_modified - e l'ID non sarà d'aiuto in quel caso. – Risadinha

+0

Sono d'accordo che ci sono alcuni casi d'angolo in cui si potrebbe voler fare qualcosa di personalizzato, ma per impostazione predefinita, ogni modello ottiene un ID autoincrementante e non vi è alcun riutilizzo dell'ID inutilizzato. Inoltre, con DateTimeField, hai un problema se due modelli finiscono con lo stesso valore nel loro DateTimeField. Ciò potrebbe accadere in base alla precisione dovuta al backend di versione/database di django. – aggieNick02

Problemi correlati