Django 1.6 и вложенность с transaction.atomic()

С годами я привык к более старым методам transaction.commit_on_success и transaction.commit_manually с Django ‹ 1.6. Но теперь с Django 1.6 старый API заменен в основном на transaction.atomic.

После прочтения документации по новому API я все еще не уверен, как следующий код будет зафиксирован в базе данных:

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

В этом примере предположим, что a_second_function_successful, вызванная из a_first_function, завершается успешно и создает/сохраняет объекты из моделей. Сразу же после того, как эта функция second_function завершается успешно, вызывается третья функция, которая завершается ошибкой.

Учитывая, что transaction.atomic с использованием контекстного менеджера используется как в первой, так и во второй функции, что произойдет с данными, созданными/измененными в a_second_function_successful. Будет ли он зафиксирован в базе данных? Будет ли откатиться автоматически из первой функции? По моему опыту, вторая функция будет зафиксирована независимо, однако я ожидал, что она не будет зафиксирована.

Будет ли теперь иметь значение, если третья функция будет определена следующим образом:

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

or as:

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

Спасибо,


person Loic Duros    schedule 02.12.2013    source источник


Ответы (1)


Ну, я бы сказал, что если у вас нет никаких попыток, кроме блоков, для перехвата исключений, вызывающих откат, тогда все будет отброшено, так как исключение будет распространяться на самый верхний with transaction.atomic() из a_first_function(), даже если оно поднято из a_third_function_fails()

Однако, если вы поймаете исключение в a_third_function_fails, это означает, что вам также придется сделать что-то вроде:

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

Тогда у вас будет откат третьей функции, а не второй функции, потому что вы неявно создаете точку сохранения, когда вызываете with transaction.atomic() из a_third_function_fails.

person j1z0    schedule 20.12.2013