2016-01-11 24 views
7

Sto tentando di creare una vista in cui salvo un oggetto ma mi piacerebbe annullare che salva se viene sollevata qualche eccezione. Questo è quello che ho provato:Django - Rollback Salva con transazione atomica

class MyView(View): 

    @transation.atomic 
    def post(self, request, *args, **kwargs): 
     try: 
      some_object = SomeModel(...) 
      some_object.save() 

      if something: 
       raise exception.NotAcceptable() 
       # When the workflow comes into this condition, I think the previous save should be undome 
       # Whant am I missing? 

     except exception.NotAcceptable, e: 
      # do something 

Cosa sto facendo male? anche quando viene sollevata l'eccezione, some_object è ancora in DataBase.

risposta

11

Atomicity Documentation

In sintesi, @transaction.atomic eseguirà una transazione sul database se la tua vista produce una risposta senza errori. Poiché stai catturando l'eccezione tu stesso, a Django sembra che la tua vista sia stata eseguita correttamente.

Se si cattura l'eccezione, è necessario gestire da soli: Controlling Transactions

Se avete bisogno di produrre una risposta JSON adeguata in caso di guasto:

from django.db import SomeError, transaction 

def viewfunc(request): 
    do_something() 

    try: 
     with transaction.atomic(): 
      thing_that_might_fail() 
    except SomeError: 
     handle_exception() 

    render_response() 
+0

Questa vista è per un'API, quindi penso di dover gestire qualsiasi errore possibile per dare una risposta jSON propper. Non c'è modo di farlo con un decoratore atomico? – Gocht

+0

Non con il decoratore, perché gestisce la transazione al di fuori della tua funzione. Bel esempio con il gestore di contesto! – jpic

+0

È necessario avere un blocco atomico all'interno del try ... tranne il blocco come nella risposta. Puoi anche usare il decoratore atomico sulla vista se lo desideri. – Alasdair

5

Tuttavia, se si verifica un'eccezione in una funzione decorato con transaction.atomic, allora non si ha nulla a che fare, sarà rollback automatically to the savepoint created by the decorator before running the your function, come documented:

atomica ci permette di creare un blocco di codice entro il quale è garantita l'atomicità sul database. Se il blocco di codice viene completato correttamente, le modifiche vengono confermate nel database. Se c'è un'eccezione, le modifiche vengono ripristinate.

Se l'eccezione viene catturato in un blocco di eccezione, allora dovrebbe essere un re-raise per Atomic per la cattura e fare il rollback, vale a dire .:

try: 
     some_object = SomeModel(...) 
     some_object.save() 

     if something: 
      raise exception.NotAcceptable() 
      # When the workflow comes into this condition, I think the previous save should be undome 
      # Whant am I missing? 

    except exception.NotAcceptable, e: 
     # do something 
     raise # re-raise the exception to make transaction.atomic rollback 

Inoltre, se si desidera un maggiore controllo , è possibile rollback manualmente previously set savepoint, vale a dire .:

class MyView(View): 
    def post(self, request, *args, **kwargs): 
     sid = transaction.savepoint() 
     some_object = SomeModel(...) 
     some_object.save() 

     if something: 
      transaction.savepoint_rollback(sid) 
     else: 
      try: 
       # In worst case scenario, this might fail too 
       transaction.savepoint_commit(sid) 
      except IntegrityError: 
       transaction.savepoint_rollback(sid) 
+0

Questo è quello che, però, e questo è perché ho fatto questa funzione in questo modo, ma come ho detto nella domanda, l'oggetto è ancora nell'evento del database quando viene sollevata un'eccezione, c'è qualche passaggio adizionale per usare i punti di salvataggio? – Gocht

+0

Forse è perché l'eccezione è stata catturata dal blocco eccetto, e non controrilanciata, quindi pensò atomicamente che la funzione fosse eseguita con successo. – jpic

+0

Se non rilevo l'errore, non posso dare una buona risposta. Come potrei costruire la mia funzione? – Gocht

Problemi correlati