代码之家  ›  专栏  ›  技术社区  ›  Bernhard Vallant

Django:更新queryset中对象的顺序属性

  •  6
  • Bernhard Vallant  · 技术社区  · 14 年前

    我的模型上有一个属性,允许用户对对象进行排序。我必须根据一个列表来更新元素的顺序,该列表以新的顺序包含对象的id;现在我正在迭代整个queryset,并一个接一个地设置一个对象。对整个queryset执行相同操作的最简单/最快的方法是什么?

    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()
    
    2 回复  |  直到 14 年前
        1
  •  5
  •   KillianDS    14 年前

    然而,你的用例是什么?整个名单真的每次都会改变吗?在大多数情况下,这似乎不太可能。我可以看到一些不同的方法。

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

    另一种方法,取决于你正在做什么,是做一个局部更新(例如使用AJAX),如果可能的话,而不是更新整个重新排序的集合,只是单独更新每个更新。这通常会增加总负载,但会随着时间的推移而更分散负载。例如,将第5个元素逐步移动到第2个位置,这将引入3个交换:(5,4)(4,3); (3,2). 结果在6个更新,而所有在一个时间内的方法只有4个将需要。但小规模的行动将随着时间的推移而展开。

        2
  •  1
  •   Collin Anderson    14 年前

    我不知道是否可以使用一个查询来完成这项工作,但在任何情况下都更有效:

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