2016-03-31 15 views
6

Ho un file di modello che utilizza un segnale post_save per creare una riga collegata in un'altra tabella. In modo tipico, posso creare una pagina da una delle mie viste che è decorata con @ transaction.atomic.I segnali di django sono inclusi anche all'interno del decoratore della transazione.

Vorrei sapere se questo decoratore inserirà la creazione dell'oggetto Pagina e l'oggetto SharedPage nella stessa transazione. Non è chiaro dai documenti di django che i segnali facciano parte di questa transazione atomica.

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

risposta

3

Sì, i segnali vengono spediti con lo stesso valore per l'impostazione autocommit di collegamento (che è ottimizzato per transaction.commit decoratore), che viene utilizzato per salvare il modello. Riferendosi il codice a django.db.models.base.Model.save_base() metodo,

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) 

Come si può vedere, nessun codice speciale viene scritto per modificare le impostazioni AUTOCOMMIT. Quindi, se la tua vista dichiara che tutta la roba relativa al database deve garantire l'atomicità usando @ transaction.atomic, allora le modifiche db fatte dalla tua vista (sia model.save() che tramite gestori di segnale), non vengono confermate, fino a quando la tua vista l'esecuzione è finita.

Spero che possa aiutarti.

Problemi correlati