سؤال

I've got used through the years to the older transaction.commit_on_success and transaction.commit_manually with Django < 1.6. But now with Django 1.6 the old API is replaced mainly with transaction.atomic.

After reading the docs on the new API, I'm still not sure how the following code will be committed to the database:

def a_first_function():
    with transaction.atomic():
        a_second_function_successful()
        a_third_function_fails()

def a_second_function_successful():
    with transaction.atomic():
        do_something()

def a_third_function_fails():
    do_something_wrong()

In this example, let's assume that a_second_function_successful called from a_first_function succeeds and creates/saves objects from models. Immediately after this second_function succeeds, the third function is called and fails.

Given that transaction.atomic using the context manager is both used in the first and second function, what will happen to the data created/modified in a_second_function_successful. Will it be committed to the database? Will it be rolled back automatically from the first function? My experience is that it the second function will be committed regardless, however, I expected it not to be committed.

Would it make any difference now if the third function was defined as the following:

@transaction.atomic
def a_third_function_fails():
    do_something_wrong()

or as:

def a_third_function_fails():
    with transaction.atomic():
        do_something_wrong()

Thanks,

هل كانت مفيدة؟

المحلول

Well I would say if you don't have any try except blocks to catch the exceptions triggering the rollback than everything will be rolled back, as the exception will propagate to the topmost with transaction.atomic() from a_first_function(), even if it is raised from a_third_function_fails()

However if you were to catch the exception in a_third_function_fails which means you would also have to do something like:

def a_third_function_fails():
    try:
        with transaction.atomic():
            do_something_wrong()
    except:
        pass

Then you would have the third function roll back and not the second function because you are implicitly creating a savepoint when you call with transaction.atomic() from a_third_function_fails.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top