Django:更新查询集中对象的顺序属性

Posted

技术标签:

【中文标题】Django:更新查询集中对象的顺序属性【英文标题】:Django: Update order attribute for objects in a queryset 【发布时间】:2011-03-04 03:41:20 【问题描述】:

我的模型上有一个属性,允许用户订购对象。我必须根据一个列表更新元素的顺序,该列表包含新顺序中的对象 ID;现在我正在遍历整个查询集并一个接一个地设置一个对象。对整个查询集执行相同操作的最简单/最快的方法是什么?

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

【问题讨论】:

【参考方案1】:

这不能在单个查询集操作中完成。据我所知,它甚至不能用原始 SQL 在一个查询中完成。因此,您将始终需要对每个必须更新的对象进行更新调用。因此,您和 Collin Anderson 的解决方案似乎都非常适合您的描述。

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

你像你说的那样保存了订单字段,但是你为订单列表生成了一个差异: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])

另一种方法,取决于您正在做什么,如果可能的话,进行部分更新(例如使用 AJAX),而不是更新整个重新排序的集合,只需单独更新每个更新。这通常会增加总负载,但随着时间的推移会分散更多。以将第 5 个元素逐步移动到位置 2 为例,这将引入 3 个交换:(5,4); (4,3); (3,2)。导致 6 次更新,而使用一次性方法只需要 4 次。但是小手术会随着时间的推移而分散。

【讨论】:

【参考方案2】:

我不知道是否可以使用一个查询来做到这一点,但无论如何这更有效:

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

【讨论】:

猜猜它只保存一次访问数据库以获取所有项目(所有项目都必须更新,因此您的解决方案也会遍历所有项目)。

以上是关于Django:更新查询集中对象的顺序属性的主要内容,如果未能解决你的问题,请参考以下文章

Django:更改查询集中所有对象的字段值

为什么图表中的列顺序与查询结果集中的列顺序不匹配?

18.07.24(查询顺序,组合)

python 2018.7.24 类空间,对象空间,查询顺序 ,组合

在 Django 中一次更新所有模型

在 Django 中更新查询集中的一堆记录的最快方法