2016-03-31 6 views
6

Ich habe eine Modelldatei, die ein post_save Signal verwendet, um eine verknüpfte Zeile in einer anderen Tabelle zu erstellen. In typischer Weise kann ich eine Seite aus einer meiner Ansichten erstellen, die mit @ transaction.atomic verziert ist.Sind Django-Signale auch innerhalb des transaction.atomic Dekorators enthalten?

Ich würde gerne wissen, ob dieser Dekorator die Erstellung des Page-Objekts und des SharedPage-Objekts in derselben Transaktion platzieren wird. Aus den Django-Dokumenten geht nicht hervor, dass Signale Teil dieser atomaren Transaktion sind.

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') 

Antwort

3

Ja, Signale mit dem gleichen Wert für autocommit Einstellung der Verbindung ausgelöst werden (die durch transaction.commit gezwickt wird Dekorator), mit dem das Modell gespeichert wird. Unter Bezugnahme den Code in django.db.models.base.Model.save_base() -Methode,

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) 

Wie Sie sehen können, ist kein spezieller Code geschrieben autocommit Einstellungen zu ändern. Also, wenn Ihre Ansicht erklärt, dass alle datenbankbezogenen Sachen atomarity sicherstellen müssen, indem Sie @ transaction.atomic verwenden, dann werden db-Änderungen, die von Ihrer Sicht (entweder model.save() oder über Signalhandler) vorgenommen werden, bis zu Ihrer Ansicht nicht festgeschrieben Die Ausführung ist beendet.

Ich hoffe, es kann Ihnen helfen.