Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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')
like image 722
Sam Texas Avatar asked Mar 31 '16 11:03

Sam Texas


People also ask

What does transaction atomic do in Django?

Django provides a single API to control database transactions. Atomicity is the defining property of database transactions. atomic allows us to create a block of code within which the atomicity on the database is guaranteed. If the block of code is successfully completed, the changes are committed to the database.

What are signals in Django what all the methods available?

There are 3 types of signal. pre_save/post_save: This signal works before/after the method save(). pre_delete/post_delete: This signal works before after delete a model's instance (method delete()) this signal is thrown. pre_init/post_init: This signal is thrown before/after instantiating a model (__init__() method).

What is created in Django signals?

The Django Signals is a strategy to allow decoupled applications to get notified when certain events occur. Let's say you want to invalidate a cached page everytime a given model instance is updated, but there are several places in your code base that this model can be updated.

What is the use of the Post_delete signal in Django?

Django Signals - post_delete() To notify another part of the application after the delete event of an object happens, you can use the post_delete signal.


1 Answers

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.

like image 140
Mangu Singh Rajpurohit Avatar answered Oct 06 '22 04:10

Mangu Singh Rajpurohit