Are django signals also included inside of the transaction.atomic decorator?

不想你离开。 提交于 2020-01-01 08:46:08

问题


I have a model file that uses a post_save signal to create a linked row in another table. In typical fashion, I can create a page from one of my views which is decorated with @transaction.atomic.

I would like to know if this decorator will put the creation of the Page object and the SharedPage object in the same transaction. It is not clear from the django docs that signals are a part of this atomic transaction.

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:


Yes, signals are dispatched with the same value for autocommit setting of connection(which is tweaked by transaction.commit decorator), which is used to save model. Referring the code in django.db.models.base.Model.save_base() method,

    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)

As you can see, no special code is written to change autocommit settings. So, if your view declares that all the database-related stuff must ensure atomicity by using @transaction.atomic, then db changes made by your view(either model.save() or through signal handlers), is not committed, until your view execution is finished.

I hope, it may help you out.



来源:https://stackoverflow.com/questions/36331753/are-django-signals-also-included-inside-of-the-transaction-atomic-decorator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!