Транзакция, начинающаяся в Django

#python #django #transactions #django-orm #django-middleware

#python #django #транзакции #django-orm #django-промежуточное программное обеспечение

Вопрос:

Я прочитал главу в документах Django об управлении транзакциями. Насколько я понимаю, транзакция запускается сразу после TransactionMiddleware вызова. Затем с помощью @commit_on_success , @commit_manually есть возможность контролировать завершение транзакции.

Мой вопрос: есть ли возможность также контролировать начало транзакции, не избавляясь от TransactionMiddleware в целом. Меня беспокоит то, что многие части Django framework на самом деле зависят от присутствия TransactionMiddleware, поэтому я действительно не хочу его нарушать. Я бы хотел, чтобы это использовалось для всех представлений, за исключением тех, которые принадлежат приложениям, которые я явно указываю. Больше всего я хотел бы иметь возможность полностью контролировать транзакционное поведение для определенной группы представлений — от начала и до конца. Какой подход я должен использовать? Есть ли какие-либо внешние приложения, библиотеки, которые могли бы мне помочь? Создаются ли транзакции быстро или лениво — как только происходит первое обращение к базе данных?

Ответ №1:

  1. Транзакции создаются с помощью первого запроса к БД.

  2. TransactionMiddleware применяет нечто подобное commit_on_success ко всем вашим представлениям. Нет необходимости добавлять это явно. commit_on_success по-прежнему полезно для придания такого поведения определенным функциям, которые вы вызываете из представления.

  3. Поддерживаются вложенные транзакции.

Итак, зачем вам нужно контролировать начало транзакции? Если вы хотите откатить только часть изменений, это следует сделать с помощью вложенных транзакций.

Вот распространенный вариант использования из моего кода:

 @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 действительно хорошая документация в коде. Похоже, это соответствует тому, что вы сказали.