【发布时间】:2011-06-22 10:59:08
【问题描述】:
这里给你一个快速的:
我有一个 id 列表,我想用它来返回一个 QuerySet(或数组,如果需要的话),但我想保持这个顺序。
谢谢
【问题讨论】:
这里给你一个快速的:
我有一个 id 列表,我想用它来返回一个 QuerySet(或数组,如果需要的话),但我想保持这个顺序。
谢谢
【问题讨论】:
从 Django 1.8 开始,您可以这样做:
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)
【讨论】:
CaseWhen被低估了!
distinct(),但出现错误。任何支持,请。
我认为您无法在数据库级别强制执行该特定顺序,因此您需要改为在 python 中执行。
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]
这会建立一个以 id 为键的对象字典,因此在建立排序列表时可以轻松检索它们。
【讨论】:
如果你想使用 in_bulk 做到这一点,你实际上需要合并上面的两个答案:
id_list = [1, 5, 7]
objects = Foo.objects.in_bulk(id_list)
sorted_objects = [objects[id] for id in id_list]
否则结果将是一个字典,而不是一个专门排序的列表。
【讨论】:
这是一种在数据库级别执行此操作的方法。复制粘贴自:blog.mathieu-leplatre.info :
MySQL:
SELECT *
FROM theme
ORDER BY FIELD(`id`, 10, 2, 1);
与 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;
与 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))
【讨论】: