2010-06-15 60 views
5

Tôi đang có một thuộc tính trên mô hình của mình để cho phép người dùng đặt hàng các đối tượng. Tôi phải cập nhật thứ tự của phần tử tùy thuộc vào một danh sách, có chứa các id của đối tượng theo thứ tự mới; ngay bây giờ tôi đang lặp qua toàn bộ queryset và thiết lập một đối tượng sau cái kia. Điều gì sẽ là cách dễ nhất/nhanh nhất để làm tương tự với toàn bộ queryset?Django: Cập nhật thuộc tính thứ tự cho các đối tượng trong một bộ truy vấn

def update_ordering(model, order): 
    """ order is in the form [id,id,id,id] for example: [8,4,5,1,3] """ 
    id_to_order = dict((order[i], i) for i in range(len(order))) 
    for x in model.objects.all(): 
     x.order = id_to_order[x.id] 
     x.save() 

Trả lời

4

này không thể được thực hiện trong một hoạt động queryset duy nhất. Theo tôi biết nó thậm chí không thể được thực hiện trong một truy vấn với SQL thô. Vì vậy, bạn sẽ luôn cần cuộc gọi cập nhật cho từng đối tượng cần được cập nhật. Vì vậy, cả hai giải pháp của bạn và Collin Anderson có vẻ khá tối ưu cho mô tả của bạn.

Tuy nhiên, trường hợp sử dụng của bạn là gì? Thực sự toàn bộ danh sách sẽ thay đổi mỗi lần? Trong hầu hết các trường hợp, điều này có vẻ rất khó xảy ra. Tôi có thể thấy một số cách tiếp cận khác nhau.

Bạn tiết kiệm lĩnh vực trật tự như bạn nói, nhưng bạn có thể tạo một diff để xem danh sách theo thứ tự: def

update_ordering(model, order): 
    """ order is in the form [id,id,id,id] for example: [8,4,5,1,3] """ 
    original_order = model.objects.value_list('id', flat=True).order_by('order') 
    order = filter(lambda x: x[1]!=x[2], zip(xrange(len(order)), order, original_order)) 
    for i in order: 
     model.objects.filter(id=i[1]).update(order=i[0]) 

cách tiếp cận khác, tùy thuộc vào những gì bạn đang làm là để làm một bản cập nhật phần (ví dụ sử dụng AJAX) nếu có thể, thay vì cập nhật toàn bộ tập hợp được sắp xếp lại, chỉ cần cập nhật từng cập nhật riêng biệt. Điều này thường sẽ làm tăng tổng tải, nhưng sẽ lan rộng theo thời gian. Lấy ví dụ như di chuyển phần tử thứ 5 theo từng bước để đặt 2, điều này sẽ giới thiệu 3 hoán đổi: (5,4); (4,3); (3.2). Kết quả trong 6 cập nhật, trong khi với cách tiếp cận tất cả-trong-một lần chỉ có 4 sẽ là cần thiết. Nhưng các hoạt động nhỏ sẽ được trải rộng theo thời gian.

1

Tôi không biết nếu nó có thể làm điều này bằng một truy vấn, nhưng đây là hiệu quả hơn trong mọi trường hợp:

def update_ordering(model, order): 
    """ order is in the form [id,id,id,id] for example: [8,4,5,1,3] """ 
    for id in model.objects.values_list('id', flat=True): 
     model.objects.filter(id=id).update(order=order.index(id)) 
+0

Đoán nó chỉ lưu nhấn db một lần để có được tất cả các mục (tất cả các mục phải được cập nhật, vì vậy giải pháp của bạn cũng lặp trên tất cả chúng). –

Các vấn đề liên quan