#python #django #transactions #django-orm #django-middleware
#python #django #транзакции #django-orm #django-промежуточное программное обеспечение
Вопрос:
Я прочитал главу в документах Django об управлении транзакциями. Насколько я понимаю, транзакция запускается сразу после TransactionMiddleware
вызова. Затем с помощью @commit_on_success
, @commit_manually
есть возможность контролировать завершение транзакции.
Мой вопрос: есть ли возможность также контролировать начало транзакции, не избавляясь от TransactionMiddleware в целом. Меня беспокоит то, что многие части Django framework на самом деле зависят от присутствия TransactionMiddleware, поэтому я действительно не хочу его нарушать. Я бы хотел, чтобы это использовалось для всех представлений, за исключением тех, которые принадлежат приложениям, которые я явно указываю. Больше всего я хотел бы иметь возможность полностью контролировать транзакционное поведение для определенной группы представлений — от начала и до конца. Какой подход я должен использовать? Есть ли какие-либо внешние приложения, библиотеки, которые могли бы мне помочь? Создаются ли транзакции быстро или лениво — как только происходит первое обращение к базе данных?
Ответ №1:
-
Транзакции создаются с помощью первого запроса к БД.
-
TransactionMiddleware
применяет нечто подобноеcommit_on_success
ко всем вашим представлениям. Нет необходимости добавлять это явно.commit_on_success
по-прежнему полезно для придания такого поведения определенным функциям, которые вы вызываете из представления. -
Поддерживаются вложенные транзакции.
Итак, зачем вам нужно контролировать начало транзакции? Если вы хотите откатить только часть изменений, это следует сделать с помощью вложенных транзакций.
Вот распространенный вариант использования из моего кода:
@transaction.commit_manually
def purchase(request, ...):
try:
... # change some data
_purchase(request, *args, **kwargs) # process purchase optimistically
except PurchaseError, ex: # My own exception class for errors we know about
_log_purchase(request, ex) # Save error in DB
messages.error(ex.human_message())
transaction.commit() # Save log entries
except:
transaction.rollback()
raise
else:
transaction.commit()
@transaction.commit_on_success
def _purchase(request, ...):
...
Комментарии:
1. Мне нужно это сделать, потому что я хочу начать транзакцию с явно заданным уровнем изоляции. В случае определенного исключения, что-то вроде этого
IsolationLevelRequired
я хочу иметь возможность перезапустить транзакцию, скажем, с более высоким уровнем изоляцииSERIALIZABLE
. Хотя это выглядит лучше, чем я ожидал, рассмотрю это сегодня. Спасибо.2. Также — django/db/transaction. у py действительно хорошая документация в коде. Похоже, это соответствует тому, что вы сказали.