问题
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