In the django 1.5- days, if I wanted to manually manage transactions (or transactions within transactions), I would do something like this:
@transaction.commit_manually
def my_method():
master_sid = transaction.savepoint()
for item in things_to_process:
inner_sid = transaction.savepoint()
# Make changes, save models, etc.
...
if I_want_to_keep_this_iterations_changes:
transaction.savepoint_commit(inner_sid)
else:
transaction.savepoint_rollback(inner_sid)
if I_want_to_keep_all_un_rolled_back_changes_from_loop:
transaction.savepoint_commit(master_sid)
else:
transaction.savepoint_rollback(master_sid)
If I'm understanding the Django docs correctly, when upgrading to Django 1.6+, I should change the above to something like this:
def my_method():
transaction.set_autocommit(False)
try:
# Same code as above
finally:
transaction.set_autocommit(True)
However, in Django 1.6+, if you call model.save() while autocommit is False, Django will raise the following error:
TransactionManagementError: The outermost 'atomic' block cannot use savepoint = False when autocommit is off.
So, how do I save a model while autocommit is false? What's the modern replacement for my old, Django 1.5 code?
You should use transaction.atomic() instead:
def my_method():
with transaction.atomic():
for item in things_to_process:
with transaction.atomic():
# Make changes, save models, etc.
...
if I_want_to_roll_back_this_iterations_changes:
raise Exception('inner rollback')
if I_want_to_roll_back_changes_from_loop:
raise Exception('mater rollback')
transaction.atomic() will handle the commit and rollback, and it can be nested.
Relevant docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With