django 信号是不是也包含在 transaction.atomic 装饰器中?

Posted

技术标签:

【中文标题】django 信号是不是也包含在 transaction.atomic 装饰器中?【英文标题】:Are django signals also included inside of the transaction.atomic decorator?django 信号是否也包含在 transaction.atomic 装饰器中? 【发布时间】:2016-07-19 19:25:48 【问题描述】:

我有一个模型文件,它使用post_save 信号在另一个表中创建链接行。以典型的方式,我可以从我的一个视图中创建一个页面,该页面装饰有@transaction.atomic。

我想知道这个装饰器是否会将 Page 对象和 SharedPage 对象的创建放在同一个事务中。从 django 文档中并不清楚信号是这个原子事务的一部分。

models.py

class Page(models.Model):
    name = models.CharField(default='My default page',max_length=200,blank=False)
    created_at = models.DateTimeField(auto_now_add=True)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    slug = models.SlugField()
    uuid = models.UUIDField(default=uuid.uuid4, editable=False)
    is_public = models.BooleanField(default=False)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

    class Meta:
        ordering = ['position','created_at']

@receiver(post_save, sender=Page)
def create_shared_page_entry(sender, instance, created, **kwargs):
    if created:
        shared_page = SharedPage.objects.create(
            page=instance,
            user=instance.user,
            can_edit=True
        )

view.py

@require_http_methods(["POST"])
@transaction.atomic
def page_create(request):
    name = request.POST.get('name')
    page = Page.objects.create(name=name, owner=request.user)

    data = serializers.serialize("json", [page])
    return HttpResponse(data, content_type='application/json')

【问题讨论】:

【参考方案1】:

是的,信号以相同的值调度连接的自动提交设置(由 transaction.commit 装饰器调整),用于保存模型。参考django.db.models.base.Model.save_base()方法中的代码,

    if not meta.auto_created:
        signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using, update_fields=update_fields)

    with transaction.atomic(using=using, savepoint=False):
        if not raw:
            self._save_parents(cls, using, update_fields)
        updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
    # Store the database on which the object was saved
    self._state.db = using
    # Once saved, this is no longer a to-be-added instance.
    self._state.adding = False

    # Signal that the save is complete
    if not meta.auto_created:
        signals.post_save.send(sender=origin, instance=self, created=(not updated),update_fields=update_fields, raw=raw, using=using)

如您所见,没有编写任何特殊代码来更改自动提交设置。因此,如果您的视图声明所有与数据库相关的内容必须通过使用@transaction.atomic 来确保原子性,那么您的视图(model.save() 或通过信号处理程序)所做的数据库更改不会提交,直到您的视图执行完毕。

希望对你有所帮助。

【讨论】:

如果我不装饰我的视图函数并使用上下文管理器with transaction.atomic(): 来创建对象怎么办?效果一样吗?

以上是关于django 信号是不是也包含在 transaction.atomic 装饰器中?的主要内容,如果未能解决你的问题,请参考以下文章

Django使用transaction.atomic“死锁”

Django - 在引发错误后对transaction.atomic块中的数据库进行操作

django信号 signal

Django 信号signal

信号(Django信号Flask信号Scrapy信号)

flask,scrapy,django信号