2010-06-15 30 views
5

我在模型上有一個屬性,允許用戶對對象進行排序。我必須根據列表更新元素的順序,該列表包含新順序中的對象的ID;現在我遍歷整個查詢集並設置一個對象。對整個查詢集執行相同操作最簡單/最快的方法是什麼?Django:查詢集中對象的更新順序屬性

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

回答

4

這不能在一個單一的查詢集操作來完成。據我所知,甚至無法用原始SQL在一個查詢中完成。所以你總是需要更新每個需要更新的對象的調用。因此,您和科林安德森的解決方案似乎都非常適合您的描述。

但是,您的用例是什麼?每一次真的整個列表都會改變嗎?在大多數情況下,這似乎不太可能。我可以看到一些不同的方法。

您保存訂單場像你說的,但是你生成的順序列表中的DIFF: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]) 

另一種方法,這取決於你正在做什麼是做部分更新(例如,使用如果可能的話,而不是更新整個重新排序的集合,只需單獨更新每個更新。這通常會增加總負載,但會隨着時間的推移而擴展。舉例來說,將第5個元素逐步移動到2,這將引入3個交換:(5,4); (4,3); (3,2)。導致6次更新,而採用一次性方法只需要4次更新。但是小型業務將隨着時間的推移而分散。

1

我不知道是否有可能做到這一點使用一個查詢,但是這是在任何情況下更有效:

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

猜測它只保存一次就可以獲取所有項目(所有項目都必須更新,因此您的解決方案也會遍歷所有項目)。 – 2010-06-24 01:11:50