2

One of my view in Django executes save operations on 6-7 tables. I want these transactions to be atomic I,e if the 5th or 6th transaction fail I want to rollback all the previous saves. The view contains a try-except block to handle the exceptions raised.

It looks something like this:

@transaction.atomic
def my_view(request):
    sid = transaction.savepoint()
    try:
        Table1.save()
        Table2.save()
        Table3.save()
        Table4.save()
        Table5.save()
        Table6.save()
        Table7.save()  # This might fail. In case of failure I want to rollback saves from Table1 to Table6

        transaction.savepoint_commit(sid)
    except Exception as e:
        print(str(e))
        transaction.savepoint_rollback(sid)
        return JsonResponse({"Status": 0, "Data": str(e)}) 

I've tried the above and Table7.save() has failed and Table1 to Table6 rollback has not happened. I want to return the JSON response as {"Status": 0, Data: "Error That occurred"} in all the cases. I don't want to re-raise the exception in except block as done in This link

What should I do to return a proper JSONResponse and rollback everything in case of failure?

shreesh katti
  • 759
  • 1
  • 9
  • 23

1 Answers1

4

As suggested in the link:

transaction.atomic will execute a transaction on the database if your view produces a response without errors. Because you're catching the exception yourself, it appears to Django that your view executed just fine. If you catch the exception, you need to handle it yourself

An alternative approach is to use transaction.atomic inside with (as context manager), which will ensure a commit or rollback (again suggested on the same link and also explained here)

def my_view(request):
    try:
        with transaction.atomic():
            Table1.save()
            Table2.save()
            Table3.save()
            Table4.save()
            Table5.save()
            Table6.save()
            Table7.save()  # This might fail. In case of failure I want to rollback saves from Table1 to Table6

    except Exception as e:
        print(str(e))
        return JsonResponse({"Status": 0, "Data": str(e)}) 
Josh Rumbut
  • 2,640
  • 2
  • 32
  • 43
anuragal
  • 3,024
  • 19
  • 27
  • We handle it ourself by using transaction.savepoint() right. Still, I'm unable to do any rollbacks. using a transaction.atomic inside "with" and catching the exception as above is not helping. So how to handle it ourselves with try-except clause was my question. – shreesh katti Feb 20 '20 at 08:46
  • @shreesh katti, the answer works fine. debug your code and make sure you're getting a failure. for example, run an exception in `save()` method of `Table7` and test again – iraj jelodari Feb 26 '20 at 21:16