Django按特定顺序从id的数组中获取QuerySet

neo*_*ser 67 arrays django

这是一个快速的你:

我有一个id列表,我想用它来返回一个QuerySet(或者数组,如果需要的话),但是我想维护那个顺序.

谢谢

Soi*_*tje 147

从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)
Run Code Online (Sandbox Code Playgroud)

  • 最佳答案,因为它实际上返回一个查询集 (9认同)
  • 我强烈推荐这是最好的答案! (3认同)
  • 我仍然认为 django 的 `Case` `When` 被低估了! (2认同)
  • 这应该是选定的答案。 (2认同)

Rei*_*cke 62

我不认为您可以在数据库级别强制执行该特定顺序,因此您需要在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]
Run Code Online (Sandbox Code Playgroud)

这将构建一个以id为键的对象字典,因此在构建排序列表时可以轻松检索它们.

  • 也许使用查询集in_bulk()方法,而不是自己构建字典? (10认同)
  • 请注意大量查询,因为在执行此操作时您将把结果存储在内存中. (3认同)

Ric*_*era 27

如果你想使用in_bulk这样做,你实际上需要合并上面的两个答案:

id_list = [1, 5, 7]
objects = Foo.objects.in_bulk(id_list)
sorted_objects = [objects[id] for id in id_list]
Run Code Online (Sandbox Code Playgroud)

否则结果将是字典而不是特定的有序列表.


use*_*ser 21

这是在数据库级别执行此操作的一种方法.复制粘贴:blog.mathieu-leplatre.info :

MySQL:

SELECT *
FROM theme
ORDER BY FIELD(`id`, 10, 2, 1);
Run Code Online (Sandbox Code Playgroud)

与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',))
Run Code Online (Sandbox Code Playgroud)

PostgreSQL:

SELECT *
FROM theme
ORDER BY
  CASE
    WHEN id=10 THEN 0
    WHEN id=2 THEN 1
    WHEN id=1 THEN 2
  END;
Run Code Online (Sandbox Code Playgroud)

与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',))
Run Code Online (Sandbox Code Playgroud)


And*_*w G 9

id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)
sorted(objects, key=lambda i: id_list.index(i.pk))
Run Code Online (Sandbox Code Playgroud)

  • 请添加一些文字来解释它是如何工作的以及为什么它可以解决OP的问题。帮助别人理解。 (2认同)