shreesh katti
shreesh katti

Reputation: 837

Django Unable to rollback with try-exception block for atomic transactions

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?

Upvotes: 2

Views: 3294

Answers (1)

Anurag
Anurag

Reputation: 3114

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

Upvotes: 4

Related Questions