使用原子计数更新查询集中的每个实例

时间:2016-12-01 11:20:47

标签: django django-queryset

我试图以原子方式更新查询集的字段。我有这样的事情:

counter = 0
for row in myQuerySet:
  row.myField = counter
  counter = counter + 1
  row.save()

这是有效的,但我想原子地这样做,因为我有数百个寄存器,这是浪费时间。我需要这样的东西:

counter = 0
myQuerySet.update(myField=(counter+=1))

但这不起作用。什么是正确的sintax?

1 个答案:

答案 0 :(得分:4)

  

这有效,但我想原子地做这个[...]

通常,答案是使用QuerySet.update method。当您想要对查询集中的所有实例执行相同的操作(或者不需要动态更改的内容)时,这是有效的。

由于您要执行的操作似乎需要依次动态更改每个实例,因此您可以使用select_for_update method

from django.db import transaction

dolors = LoremIpsum.objects.select_for_update().filter(dolor=True)

with transaction.atomic():
    counter = 0
    for lorem_ipsum in dolors:
        lorem_ipsum.amet = counter
        counter += 1
        lorem_ipsum.save()

documentation for select_for_update说这可以做你想要的:

  

所有匹配的条目将被锁定,直到事务块结束,这意味着将阻止其他事务更改或获取锁定。

因为查询集导致项目“锁定到事务块结束”,所以您需要使用上面的transaction.atomic在事务块内执行操作。