我有一个简单的库应用程序。为了强制将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。
答案 0 :(得分:3)
您正确使用transaction.atomic()
(包括将try ... except
放在交易之外)但您绝对不应该设置AUTOCOMMIT = False
。
正如documentation所述,当你想要“禁用Django的事务管理”时,你将系统范围的设置设置为False
- 但显然不你想要什么要做,因为你正在使用transaction.atomic()
!更多来自documentation:
如果你这样做,Django将不会启用自动提交,也不会执行任何提交。您将获得底层数据库库的常规行为。 这要求您明确提交每个事务,甚至是由Django或第三方库启动的事务。因此,这最适用于您想要运行自己的事务控制中间件或做一些非常奇怪的事情的情况。
所以就是不要这样做。 Django当然会禁用该原子块的自动提交,并在块完成时重新启用它。