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

时间:2016-08-31 07:01:15

标签: python django django-queryset

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

1 个答案:

答案 0 :(得分:1)

<强>第一

作为docs

  

Atomicity是数据库事务的定义属性。 atomic允许我们创建一个代码块,在该代码块中保证数据库的原子性。如果代码块成功完成,则更改将提交到数据库。如果存在异常,则会回滚更改。

在您的示例中,如果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')

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