2016-03-31 1 views
6

J'ai un fichier modèle qui utilise un signal post_save pour créer une ligne liée dans une autre table. De façon typique, je peux créer une page à partir d'une de mes vues qui est décorée avec @ transaction.atomic.Les signaux django sont-ils également inclus dans la transaction.atomic décorator?

Je voudrais savoir si ce décorateur mettra la création de l'objet Page et de l'objet SharedPage dans la même transaction. Il n'est pas clair à partir des docs django que les signaux font partie de cette transaction atomique.

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

Répondre

3

Oui, les signaux sont envoyés à la même valeur pour le réglage d'auto-validation de la connexion (qui est pincé par transaction.Commit décorateur), qui est utilisé pour enregistrer le modèle. En référence le code dans la méthode django.db.models.base.Model.save_base(),

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) 

Comme vous pouvez le voir, aucun code spécial est écrit pour modifier les paramètres de validation automatique. Donc, si votre vue déclare que tout ce qui concerne la base de données doit assurer l'atomicité en utilisant @ transaction.atomic, alors les changements de db effectués par votre vue (soit model.save() ou via les gestionnaires de signal), ne sont pas validés, jusqu'à ce que votre vue l'exécution est terminée.

J'espère que cela pourra vous aider.