控制Django中的原子事务

时间:2016-06-13 16:58:18

标签: python mysql django atomicity

我有一个简单的库应用程序。为了强制将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 个答案:

答案 0 :(得分:3)

您正确使用transaction.atomic()(包括将try ... except放在交易之外)但您绝对不应该设置AUTOCOMMIT = False

正如documentation所述,当你想要“禁用Django的事务管理”时,你将系统范围的设置设置为False - 但显然你想要什么要做,因为你正在使用transaction.atomic()!更多来自documentation

  

如果你这样做,Django将不会启用自动提交,也不会执行任何提交。您将获得底层数据库库的常规行为。   这要求您明确提交每个事务,甚至是由Django或第三方库启动的事务。因此,这最适用于您想要运行自己的事务控制中间件或做一些非常奇怪的事情的情况。

所以就是不要这样做。 Django当然会禁用该原子块的自动提交,并在块完成时重新启用它。