2016-06-13 15 views
1

Ich habe eine einfache Bibliotheksanwendung. Um 3 Aktionen zu zwingen, als eine Aktion zu begehen, und Rollback, wenn eine der Aktionen scheitern, habe ich die folgenden Code-Änderungen:Kontrolle atomarer Transaktionen in Django

In settings.py:

AUTOCOMMIT=False 

In forms.py

from django.db import IntegrityError, transaction 
    class CreateLoan(forms.Form): 
     #Fields... 
     def save(self): 
      id_book = form.cleaned_data.get('id_book', None) 
      id_customer = form.cleaned_data.get('id_customer', None) 
      start_date = form.cleaned_data.get('start_date', None) 
      book = Book.objects.get(id=id_book) 
      customer = Customer.objects.get(id=id_customer) 
      new_return = Return(
       book=book 
       start_date=start_date) 
      txn=Loan_Txn(
       customer=customer, 
       book=book, 
       start_date=start_date 
      ) 

      try 
       with transaction.atomic(): 
        book.update(status="ON_LOAN") 
        new_return.save(force_insert=True) 
        txn.save(force_insert=True) 
      except IntegrityError: 
       raise forms.ValidationError("Something occured. Please try again") 

Fehle mir noch was dazu? Ich benutze Django 1.9 mit Python 3.4.3 und die Datenbank ist MySQL.

+2

Warum setzen Sie 'AUTOCOMMIT = False'? Tu das nicht. Sonst hast du die richtige Idee. –

+0

@KevinChristopherHenry, um die Schleife zu schließen, kann ich fragen, warum 'AUTOCOMMIT = False' hilft nicht bei der Abfrage? Ist es richtig zu sagen, dass "AUTOCOMMIT = True" und für alle Transaktionen, die nicht in einen "atomaren" Block gehüllt sind, sie nur ausführen und committen? – bryansis2010

+0

Das ist richtig, siehe meine Antwort für weitere Details. –

Antwort

2

Sie verwenden transaction.atomic() korrekt (einschließlich der außerhalb der Transaktion setzen), aber Sie sollten auf keinen Fall AUTOCOMMIT = False einstellen.

Da die documentation Staaten, setzen Sie diese systemweite Einstellung False, wenn Sie wollen „Djangos Transaktionsmanagement deaktivieren“ -aber das klar nicht, was Sie tun wollen, da Sie transaction.atomic() verwenden! Mehr aus der documentation:

Wenn Sie dies tun, wird Django Autocommit nicht aktivieren und keine Commits ausführen. Sie erhalten das normale Verhalten der zugrunde liegenden Datenbankbibliothek. Dies erfordert, dass Sie jede Transaktion explizit bestätigen, selbst wenn diese von Django oder von Bibliotheken von Drittanbietern gestartet wurde. Daher wird dies am besten in Situationen verwendet, in denen Sie Ihre eigene Transaktionssteuerungs-Middleware ausführen oder etwas wirklich seltsames tun möchten.

Also tun Sie das nicht. Django wird natürlich Autocommit für diesen atomaren Block deaktivieren und ihn wieder aktivieren, wenn der Block fertig ist.