2011-09-09 23 views
14

Tôi có ID theo một thứ tự cụ thểdjango: __in tra cứu truy vấn không duy trì trật tự trong querset

>>> album_ids = [24, 15, 25, 19, 11, 26, 27, 28] 
>>> albums = Album.objects.filter(id__in=album_ids, published= True) 
>>> [album.id for album in albums] 
[25, 24, 27, 28, 26, 11, 15, 19] 

Tôi cần album trong queryset theo thứ tự như của id trong album_ids. Bất cứ ai xin vui lòng cho tôi biết làm thế nào tôi có thể duy trì thứ tự? hoặc lấy các album như trong album_ids?

Trả lời

13

Giả sử danh sách các ID không phải là quá lớn, bạn có thể chuyển đổi các QS vào một danh sách và sắp xếp nó bằng Python:

album_list = list(albums) 
album_list.sort(key=lambda album: album_ids.index(album.id)) 
+0

Tôi có cơ sở dữ liệu lớn, ID có thể là hàng triệu – Ahsan

+0

Chỉ để tham khảo trong tương lai, tôi nghĩ thực tế rằng ID có thể là hàng triệu không có liên quan trong hầu hết các ứng dụng vì chúng tôi cần phải tải một lượng thông tin như vậy. Thay vào đó, bạn có thể sử dụng django-pagination chỉ tải số lượng cần thiết để hiển thị và làm cho trải nghiệm người dùng tốt hơn. –

+1

Đây là một giải pháp tốt đẹp, nhưng làm thế nào để làm điều đó giữ QuerySet để làm theo nó? –

9

Bạn không thể làm điều đó trong django qua ORM. Nhưng nó khá đơn giản để thực hiện bởi bản thân bạn:

album_ids = [24, 15, 25, 19, 11, 26, 27, 28] 
albums = Album.objects.filter(published=True).in_bulk(album_ids) # this gives us a dict by ID 
sorted_albums = [albums[id] for id in albums_ids if id in albums] 
17

Kể từ Djnago 1.8 bạn có thể làm theo cách này

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

Điều này nghe có vẻ tuyệt vời vì kết quả cuối cùng là một queryset trái ngược với các câu trả lời khác tạo ra các danh sách. –

+0

Câu trả lời hay nhất! Cảm ơn Arun! – nextdoordoc

1

Bạn có thể làm điều đó trong Django qua ORM sử dụng modifier extra QuerySet

>>> album_ids = [24, 15, 25, 19, 11, 26, 27, 28] 
>>> albums = Album.objects.filter(id__in=album_ids, published= True 
      ).extra(select={'manual': 'FIELD(id,%s)' % ','.join(map(str, album_ids))}, 
        order_by=['manual']) 
Các vấn đề liên quan