rất nhanh cho bạn:
Tôi có một danh sách các id mà tôi muốn sử dụng để trả về một QuerySet (hoặc mảng nếu cần), nhưng tôi muốn duy trì thứ tự đó.
Cảm ơn
Câu trả lời:
Tôi không nghĩ rằng bạn có thể thực thi thứ tự cụ thể đó trên cấp cơ sở dữ liệu, vì vậy thay vào đó bạn cần thực hiện nó trong 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]
Điều này xây dựng một từ điển của các đối tượng với id của chúng là khóa, vì vậy chúng có thể được truy xuất dễ dàng khi xây dựng danh sách đã sắp xếp.
Kể từ Django 1.8, bạn có thể làm:
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)
Case
When
được đánh giá thấp!
distinct()
với mệnh đề order_by case when nhưng gặp lỗi. bất kỳ hỗ trợ, xin vui lòng.
SELECT DISTINCT ON expressions must match initial ORDER BY expressions
- đây là thông báo lỗi
Nếu bạn muốn thực hiện việc này bằng cách sử dụng in_bulk, bạn thực sự cần kết hợp hai câu trả lời ở trên:
id_list = [1, 5, 7]
objects = Foo.objects.in_bulk(id_list)
sorted_objects = [objects[id] for id in id_list]
Nếu không, kết quả sẽ là một từ điển hơn là một danh sách được sắp xếp cụ thể.
Đây là một cách để làm điều đó ở cấp cơ sở dữ liệu. Sao chép dán từ: blog.mathieu-leplatre.info :
MySQL :
SELECT *
FROM theme
ORDER BY FIELD(`id`, 10, 2, 1);
Tương tự với 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;
Tương tự với 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))