Управляйте атомарными транзакциями в Джанго

У меня есть простое приложение библиотеки. Чтобы принудительно зафиксировать 3 действия как одно действие и выполнить откат в случае сбоя какого-либо из этих действий, я внес следующие изменения в код:

В settings.py:

AUTOCOMMIT=False

В forms.py

from django.db import IntegrityError, transaction
    class CreateLoan(forms.Form):
        #Fields...
        def save(self):
            id_book = form.cleaned_data.get('id_book', None)
            id_customer = form.cleaned_data.get('id_customer', None)
            start_date = form.cleaned_data.get('start_date', None)
            book = Book.objects.get(id=id_book)
            customer = Customer.objects.get(id=id_customer)
            new_return = Return(
                book=book
                start_date=start_date)
            txn=Loan_Txn(
                customer=customer,
                book=book,
                start_date=start_date
            )

            try
                with transaction.atomic():
                    book.update(status="ON_LOAN")
                    new_return.save(force_insert=True)
                    txn.save(force_insert=True)
            except IntegrityError:
                raise forms.ValidationError("Something occured. Please try again")

Я все еще что-то упускаю в отношении этого? Я использую Django 1.9 с Python 3.4.3, а база данных - MySQL.

1 ответ

Решение

Вы используете transaction.atomic() правильно (в том числе положить try ... except вне транзакции) но вы точно не должны устанавливать AUTOCOMMIT = False,

Как указано в документации, вы устанавливаете эту общесистемную настройку на False когда вы хотите "отключить управление транзакциями в Django", но это явно не то, что вы хотите сделать, так как вы используете transaction.atomic()! Больше из документации:

Если вы сделаете это, Django не включит автокоммит и не выполнит никаких коммитов. Вы получите обычное поведение базовой библиотеки базы данных. Это требует от вас явной фиксации каждой транзакции, даже если она запущена Django или сторонними библиотеками. Таким образом, это лучше всего использовать в ситуациях, когда вы хотите запустить собственное промежуточное программное обеспечение для управления транзакциями или сделать что-то действительно странное.

Так что просто не делай этого. Django, конечно, отключит автокоммит для этого атомарного блока и снова включит его, когда блок завершится.

Другие вопросы по тегам