Это работает, но я хочу сделать это атомарно [...]
Часто, ответ заключается в использовании 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
говорит, что это делает то, что вы хотите:
Все совпадающие записи будут заблокированы до конца блока транзакции, а это означает, что другие операции будут предотвращены от изменения или приобретения замков на них ,
Поскольку QuerySet вызывает элементы не должны быть «закрыты до конца блока транзакции», вам необходимо выполнить свои операции внутри блока транзакции с использованием transaction.atomic
, как указано выше.
Оператор update создает один SQL-запрос, и если вы используете значение, которое не является частью таблицы (т. Е. Оно не является полем), оно будет считаться константой, и в этом случае все строки будут обновляться одинаковыми стоимость. – AKS
Объекты 'F()' могут помочь обновить поле на основе существующего значения поля, но я не могу придумать способ обновления поля на основе возрастающего внешнего значения. –
@Sayse У меня много регистров с целым полем «step_number». Это поле может быть изменено вручную, и вы можете получить инкрементную последовательность с зазорами, например, если у вас есть 5 регистров, их step_numbers могут быть 1,2,3,8,9. Но я хочу перенумеровать это, чтобы получить последовательность 1,2,3,4,5. Такова цель счетчика. – MouTio