2010-09-02 9 views
13

Angesichts einer Liste von IDs/Pks, möchte ich eine QuerySet von Objekten durch den Index in der Liste geordnet generieren.Django QuerySet Benutzerdefinierte Sortierung nach ID

Normalerweise würde ich beginnen mit:

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

Dies ist natürlich die Objekte zurückgibt, sondern in der Reihenfolge der Modelle Meta Ordnungseigenschaft, und ich wünsche die Datensätze in der Reihenfolge der pk s erhalten in pk_list.

Das Endergebnis hat einQuerySet Objekt (keine Liste) sein, wie ich das bestellen QuerySet zu Djangos ModelMultipleChoiceField Formularfeld übergeben will.

+1

Bei db Ebene für MySQL & PostgreSQL: http://blog.mathieu-leplatre.info/django-create-a-queryset-from-a-list-preserving-order.html – Medorator

Antwort

1

Ich kenne keine Möglichkeit, dies mithilfe einer Filterbedingung zu tun. Wenn Ihre Datenbank die Zeilen in der Reihenfolge der IN-Klausel zurückgibt, dann können Sie in der Lage sein, die extra-Methode von Django mit der von Ihrer Datenbank bereitgestellten ROWNUM zu kombinieren, um dies zu erreichen.

Für z.B .:

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

Wo row_num() angenommen wird, eine Datenbankfunktion sein, die die Zeilennummer der aktuellen Zeile zurückgibt. Postgresql 8.4+ unterstützt row_num(), aber ich weiß nicht, wie die zurückgegebenen Zeilen in derselben Reihenfolge wie die Werte in der IN-Klausel zurückgegeben werden.

Ich denke, ein besserer Weg wäre Sub-Klasse ModelMultipleChoiceField und fügen Sie benutzerdefinierte Sortierlogik beim Rendern.

+0

Danke dafür, aber ich brauche etwas, das sowohl mit sqlite als auch mit mysql kompatibel ist. Ich denke, ich benutze 'MultipleChoiceField' und erzeuge die Auswahlliste selbst. –

7

Es gibt keine integrierte Möglichkeit, dies zu tun.

Wenn Sie MySQL verwenden, können Sie die FIELD()-Funktion dieser Datenbank verwenden, um eine benutzerdefinierte Reihenfolge für die Reihenfolge in Ihrem Modell einzurichten und nach dieser zu sortieren. Dies würde funktionieren:

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

Danke dafür, aber ich brauche etwas, das sowohl mit sqlite als auch mit mysql kompatibel sein wird. Ich denke, ich benutze 'MultipleChoiceField' und erzeuge die Auswahlliste selbst. –

+0

warten, 'order_by = 'pk'' funktioniert nicht? – amirouche

+1

@amirouche, nein er will es in einer Reihenfolge ganz anders als einfache numerische Sortierung. – LarrikJ