Django - Atom transaction rollback

I am trying to create a view in which I save an object, but I would like to cancel it if some kind of exception is thrown. This is what I tried:

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 

What am I doing wrong? even when an exception some_object is still in the database.

+26
python django atomicity transactions django-database
source share
3 answers

Atomic Documentation

To summarize, @transaction.atomic will execute the transaction in the database if your view returns an error-free response. Since you are throwing the exception yourself, Django seems like your submission performed just fine.

If you catch an exception, you need to handle it yourself: Transaction Management

If you need to create the correct json response in case of failure:

 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() 
+32
source share

However, if an exception occurs in the function decorated with the .atomic transaction, then you have nothing to do, it will automatically roll back to save the point created by the decorator before running your function , as documented :

atomic allows us to create a block of code that guarantees atomicity in the database. If the code block completes successfully, the changes are bound to the database. If there is an exception, the changes are rolled back.

If the exception falls into the exception block, then it must be re-raised for the atom to catch it and roll back, i.e.:

  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 

In addition, if you want more control, you can manually cancel the command from the previously set savepoint , i.e.:

 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) 
+14
source share

For me, this works in Django 2.2.5

First of all, in your settings.py

 ... DATABASES = { 'default': { 'ENGINE': 'xxx', # transactional db ... 'ATOMIC_REQUESTS': True, } } 

And in your function (views.py)

 from django.db import transaction @transaction.atomic def make_db_stuff(): # do stuff in your db (inserts or whatever) if success: return True else: transaction.set_rollback(True) return False 
0
source share

All Articles