Django按特定顺序从ID数组获取QuerySet


83

这是一个快速的为您服务的:

我有一个ID列表,我想用它返回QuerySet(或数组(如果需要的话)),但是我想保持该顺序。

谢谢

Answers:


73

我认为您无法在数据库级别上执行该特定命令,因此您需要使用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为键的对象字典,因此在建立排序列表时可以轻松检索它们。


我希望不是这样:(感谢您提供的干净代码!
neolaser

3
只是要提防庞大的查询,因为这样做时会将结果存储在内存中。
Jj。

12
也许使用querysets in_bulk()方法,而不是自己构造字典?
Matt Austin

问题是如果id_list中的对象不存在,它将引发错误。
madprops

为什么不使用dict理解?
wieczorek1990 '16

180

从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)

15
最佳答案,因为它实际上返回了一个查询集
Teebes

1
我仍然认为Django的价值Case When被低估了!
巴布(Babu)

我将distinct()与order_by case when子句一起使用,但出现了错误。请提供任何支持。
elquimista

SELECT DISTINCT ON expressions must match initial ORDER BY expressions-这是错误消息
elquimista

我强烈建议这是最佳答案!
托尼

28

如果要使用in_bulk进行此操作,则实际上需要合并以上两个答案:

id_list = [1, 5, 7]
objects = Foo.objects.in_bulk(id_list)
sorted_objects = [objects[id] for id in id_list]

否则,结果将是字典而不是特定排序的列表。


1
这不是一个更好的答案。
托尼

25

这是在数据库级别执行此操作的方法。复制粘贴自: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',))

哇。好激烈 谢谢!
Dan Gayle 2014年

感谢您的回答。
Subangkar KrS

9
id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)
sorted(objects, key=lambda i: id_list.index(i.pk))

1
请添加一些文字,说明其工作原理以及为什么可以解决OP的问题。帮助他人了解。
APC

最佳答案。谢谢!
webjunkie

效果很好,尽管可以使用其他信息
xtrinch

这仅适用于有序的idlist。您能确认它是否可以按任何顺序工作...在我看来似乎不正确。
Doogle
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.