Is the post_save signal in Django atomic?
Asked Answered
M

1

9

I really can't find anything solid in the docs. Lets say I'm doing something like this:

from django.db.models.signals import post_save
from django.dispatch import receiver

class Item(models.Model):
    total_score = models.IntegerField()

    def set_score(self):
         ...

class Review(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    score = models.IntegerField()

@receiver(post_save, sender=Review)
def my_handler(sender, **kwargs):
    sender.item.set_score()

What I'm trying to do is call set_score() for the item object, whenever a review object is saved. Is this atomic? I definitely want the whole thing to be atomic, as a situation where a review is saved, but the item's total score is not updated is a recipe for bugs.

Matronize answered 6/4, 2019 at 18:29 Comment(0)
B
12

No, there's nothing special about signals with regard to database transactions (the only kind of atomicity handled by Django). It's up to you to ensure that the relevant commands are always part of the same database transaction.

One approach would be to simply rely on the calling code to do this by using ATOMIC_REQUESTS, using transactions in your views, etc.

Or, since post_save signals are sent as part of Model.save(), you could simply override Review.save() and make it use a transaction.

class Review(models.Model):
    ...

    @transaction.atomic()
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
Best answered 6/4, 2019 at 23:58 Comment(3)
Using transaction.set_rollback(True) in my code proved this approach to be wrong. Changes applied in a signal that is triggered by a @transaction.atomic-decorated function are rolled back.Definiendum
@QCaron: "Changes applied in a signal that is triggered by a @transaction.atomic-decorated function are rolled back." I agree. That doesn't contradict my answer. Note that the OP did not use @transaction.atomic.Best
Indeed, I should suggest another answer as the question is a little ambiguous: a signal is described in the code example but it also states "whenever a review object is saved"...Definiendum

© 2022 - 2024 — McMap. All rights reserved.