django queryset.update(**kwargs) 上的原子事务

问题描述 投票:0回答:1

看起来

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
之后,我的查询集变空,因为它是经过过滤的查询集。当我想在各个对象上发出事件时,如何保留我的情况下的值。

python django django-queryset
1个回答
5
投票

更新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')

看到我们在迭代查询集以获取更新的项目时创建了新的查询集

© www.soinside.com 2019 - 2024. All rights reserved.