Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django 1.6 - "The outermost 'atomic' block cannot use savepoint = False when autocommit is off."

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?

like image 243
Troy Avatar asked Oct 20 '22 14:10

Troy


1 Answers

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

like image 56
sp1111 Avatar answered Oct 27 '22 10:10

sp1111