Program Tip

Django는 특정 순서로 id 배열에서 QuerySet을 가져옵니다.

programtip 2020. 11. 12. 20:07
반응형

Django는 특정 순서로 id 배열에서 QuerySet을 가져옵니다.


여기에 빠른 것이 있습니다.

QuerySet (또는 필요한 경우 배열)을 반환하는 데 사용하려는 ID 목록이 있지만 그 순서를 유지하고 싶습니다.

감사


나는 당신이 데이터베이스 수준에서 특정 순서를 강요 할 수 없다고 생각하기 때문에 대신 파이썬으로해야한다.

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를 키로 사용하여 객체 사전이 구축되므로 정렬 된 목록을 구축 할 때 쉽게 검색 할 수 있습니다.


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)

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

참고 URL : https://stackoverflow.com/questions/4916851/django-get-a-queryset-from-array-of-ids-in-specific-order

반응형