看起来
Django
的 queryset.update
方法是在 transaction.atomic
上下文管理器下执行的。我什么时候需要在 update
期间在代码中明确执行此操作?或者说这样做会有什么好处,或者不这样做会有什么问题?
try:
queryset = Model.objects.filter(a=1)
if queryset.count():
with transaction.atomic():
queryset.update(a=2) # queryset will [] after this.
for item in queryset:
item.emit_event('Updated')
except:
logger.info('Exception')
我的问题是我真的需要在这里有
transaction.atomic():
吗?
其次,在
.update
之后,我的查询集变空,因为它是经过过滤的查询集。当我想在各个对象上发出事件时,如何保留我的情况下的值。
更新2023年8月30日
select_for_update
在大多数情况下您可能想使用它。
第一
如文档状态
原子性是数据库事务的定义属性。原子允许我们创建一个代码块,在其中保证数据库的原子性。如果代码块成功完成,则更改将提交到数据库。如果出现异常,更改将回滚。
在您的示例中,如果
atomic
正在执行某些操作,并且您希望仅在所有 emit_event
函数调用和 emit_event
成功时才能完成此更新,则需要 queryset.update
。但是,如果 emit_event
的状态不影响您更新的业务逻辑,那么此处的 atomic
将是多余的,因为正如您自己所说,update
具有内部 atomic
。
第二个
查询集是惰性的。这意味着当您迭代查询集时,将完成对查询集的评估。所以你需要做这样的事情。回复最新评论
try:
queryset = Model.objects.filter(a=1)
item_ids = list(queryset.values_list('id', flat=True)) # store ids for later
if item_ids: # optimzing here instead of queryset.count() so there won't be hit to DB
with transaction.atomic():
queryset.update(a=2) # queryset will [] after this.
for item in Model.objects.filter(id__in=item_ids): # <- new queryset which gets only updated objects
item.emit_event('Updated')
except:
logger.info('Exception')
看到我们在迭代查询集以获取更新的项目时创建了新的查询集