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

Update every instance in a queryset with a count atomically

我正在尝试以原子方式更新查询集的字段。我有这样的东西:

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

可行,但我想以原子方式执行此操作,因为我有数百个寄存器,这是浪费时间。我需要这样的东西:

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

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

That works, but I want to do this atomically […]

通常,答案是使用 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 说这就是你想要的:

All matched entries will be locked until the end of the transaction block, meaning that other transactions will be prevented from changing or acquiring locks on them.

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