Hier ist eine schnelle für Sie:
Ich habe eine Liste von IDs, mit denen ich ein QuerySet (oder ggf. ein Array) zurückgeben möchte, aber ich möchte diese Reihenfolge beibehalten.
Vielen Dank
Antworten:
Ich glaube nicht, dass Sie diese bestimmte Reihenfolge auf Datenbankebene erzwingen können, also müssen Sie dies stattdessen in Python tun.
id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)
objects = dict([(obj.id, obj) for obj in objects])
sorted_objects = [objects[id] for id in id_list]
Dadurch wird ein Wörterbuch der Objekte mit ihrer ID als Schlüssel erstellt, sodass sie beim Erstellen der sortierten Liste leicht abgerufen werden können.
Seit Django 1.8 können Sie Folgendes tun:
from django.db.models import Case, When
pk_list = [10, 2, 1]
preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)])
queryset = MyModel.objects.filter(pk__in=pk_list).order_by(preserved)
Case Whenunterschätzt werden!
distinct()mit order_by case when-Klausel verwenden, habe aber den Fehler erhalten. jede Unterstützung bitte.
SELECT DISTINCT ON expressions must match initial ORDER BY expressions- Hier ist die Fehlermeldung
Wenn Sie dies mit in_bulk tun möchten, müssen Sie die beiden obigen Antworten zusammenführen:
id_list = [1, 5, 7]
objects = Foo.objects.in_bulk(id_list)
sorted_objects = [objects[id] for id in id_list]
Andernfalls ist das Ergebnis eher ein Wörterbuch als eine speziell geordnete Liste.
Hier ist eine Möglichkeit, dies auf Datenbankebene zu tun. Kopieren Einfügen von: blog.mathieu-leplatre.info :
MySQL :
SELECT *
FROM theme
ORDER BY FIELD(`id`, 10, 2, 1);
Gleiches gilt für Django:
pk_list = [10, 2, 1]
ordering = 'FIELD(`id`, %s)' % ','.join(str(id) for id in pk_list)
queryset = Theme.objects.filter(pk__in=[pk_list]).extra(
select={'ordering': ordering}, order_by=('ordering',))
PostgreSQL :
SELECT *
FROM theme
ORDER BY
CASE
WHEN id=10 THEN 0
WHEN id=2 THEN 1
WHEN id=1 THEN 2
END;
Gleiches gilt für Django:
pk_list = [10, 2, 1]
clauses = ' '.join(['WHEN id=%s THEN %s' % (pk, i) for i, pk in enumerate(pk_list)])
ordering = 'CASE %s END' % clauses
queryset = Theme.objects.filter(pk__in=pk_list).extra(
select={'ordering': ordering}, order_by=('ordering',))
id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)
sorted(objects, key=lambda i: id_list.index(i.pk))