Ghopper21
Ghopper21

Reputation: 10477

Nested manually commited transactions in Django

Let's say I have a view function foo that calls model method bar. Both foo and bar are decorated with @method_decorator(transaction.commit_manually). Both always do a transaction.rollback() before returning.

Will this nested rollback work as intended, i.e. that no database changes happen when foo is called?

(From my testing, it seems to work, but I'm uncertain as I couldn't find anything definitive about Django transactions that applied to this case. Note I'm using Django 1.4 with PostgreSQL 9.1.4.)

Upvotes: 3

Views: 896

Answers (1)

Krzysztof Rosiński
Krzysztof Rosiński

Reputation: 1478

You must be careful here, the DB commit/rollback is connection level, if You have something like this:

@transaction.commit_manually
def foo():
   bar()
   transaction.rollback()

@transaction.commit_manually
def bar()
   #some db op
   transaction.commit()

#running
foo()

changes to the database will be commited, You should put @transaction.commit_manually on top level functions. In django 1.6 transaction.atomic decorator was introduced which generally provides what you are looking for:

atomic blocks can be nested. In this case, when an inner block completes successfully, its effects can still be rolled back if an exception is raised in the outer block at a later point

On the other hand You just make rollbacks it should be OK (if you want to stick to 1.4), as long as the commit is on the top level only, but it's best to keep the transaction management on one level in this case (for example raising Exceptions and handling them in foo())

Upvotes: 4

Related Questions