Django以特定顺序从id数组中获取一个QuerySet

67up9zun  于 2022-11-26  发布在  Go
关注(0)|答案(6)|浏览(109)

这里有一个快速的一个给你:
我有一个id的列表,我想用它来返回一个QuerySet(或者数组,如果需要的话),但是我想保持这个顺序。
谢谢

h79rfbju

h79rfbju1#

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

vshtjzan2#

我不认为你可以在数据库级别上强制执行这个特定的顺序,所以你需要用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作为关键字,因此在建立排序列表时可以轻松地检索它们。

cigdeys3

cigdeys33#

如果您想使用in_bulk来完成此操作,实际上需要合并上面的两个答案:

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

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

5kgi1eie

5kgi1eie4#

下面是在数据库级别执行此操作的方法。复制粘贴自:blog.mathieu-leplatre.info

数据库

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',))
fgw7neuy

fgw7neuy5#

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

flmtquvp6#

另一种更好/更干净的方法可以是

pk_list = [10, 2, 1]
sorted_key_object_pair = MyModel.objects.in_bulk(pk_list)
sorted_objects = sorted_key_object_pair.values()

简单、干净、代码少。

相关问题