2010-09-02 17 views
13

Dato un elenco di id/pks, mi piacerebbe generare uno QuerySet di oggetti ordinati dall'indice nell'elenco.Django QuerySet Ordine personalizzato per ID

Normalmente mi piacerebbe cominciare con:

pk_list = [5, 9, 2, 14] 
queryset = MyModel.objects.filter(pk__in=pk_list) 

Questo naturalmente restituisce gli oggetti, ma nell'ordine dei modelli di proprietà ordinazione meta, e mi auguro di ottenere i record nell'ordine dei pk s in pk_list.

il risultato finale deve essere un QuerySet oggetto (non una lista), come vorrei passare il ordinato QuerySet al campo ModelMultipleChoiceField forma di Django.

+1

A livello db per MySQL e PostgreSQL: http://blog.mathieu-leplatre.info/django-create-a-queryset-from-a-list-preserving-order.html – Medorator

risposta

1

Non conosco un modo per farlo utilizzando una condizione di filtro. Se il tuo database restituirà le righe nell'ordine della clausola IN allora tu puoi essere in grado di combinare il metodo extra di Django con il ROWNUM fornito dal tuo database per raggiungere questo obiettivo.

Per es .:

queryset = MyModel.objects.filter(pk__in=[pk_list]).extra(
     select: {'rownum': 'row_num()'}).order_by('rownum') 

Dove row_num() si presume essere una funzione database che restituisce il numero di riga della riga corrente. Postgresql 8.4+ supporta row_num() ma non so come ordinare le righe restituite utilizzando lo stesso ordine dei valori nella clausola IN.

Penso che un modo migliore sarebbe quello di sottoclasse ModelMultipleChoiceField e aggiungere logica di ordinamento personalizzata durante il rendering.

+0

Grazie per questo, ma ho bisogno di qualcosa che sia compatibile con sqlite e mysql. Penso che userò 'MultipleChoiceField' e genererò la lista delle scelte da solo. –

7

Non c'è un modo integrato per farlo.

Se si utilizza MySQL, è possibile utilizzare la funzione FIELD() del database per impostare una sequenza di ordinazione personalizzata sul modello e ordinare in base a tale. Questo dovrebbe funzionare:

pk_list = [5, 9, 2, 14] 
ordering = 'FIELD(`id`, %s)' % ','.join(str(id) for id in pk_list) 
queryset = MyModel.objects.filter(pk__in=[pk_list]).extra(
       select={'ordering': ordering}, order_by=('ordering',)) 
+0

Grazie per questo, ma ho bisogno di qualcosa che sia compatibile con sqlite e mysql. Penso che userò 'MultipleChoiceField' e genererò la lista delle scelte da solo. –

+0

wait, 'order_by = 'pk'' non funziona? – amirouche

+1

@amirouche, no lo vuole in un ordine del tutto diverso dal semplice tipo numerico. – LarrikJ