在 Django 中控制原子事务
Control Atomic Transactions in Django
我有一个简单的图书馆应用程序。为了强制将 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")
关于这个,我还遗漏了什么吗?我在 Python 3.4.3 中使用 Django 1.9,数据库是 MySQL.
您正确使用了 transaction.atomic()
(包括将 try ... except
置于交易之外),但您绝对不应该设置 AUTOCOMMIT = False
.
作为 documentation states, you set that system-wide setting to False
when you want to "disable Django’s transaction management"—but that's clearly not what you want to do, since you're using transaction.atomic()
! More from the documentation:
If you do this, Django won’t enable autocommit, and won’t perform any commits. You’ll get the regular behavior of the underlying database library.
This requires you to commit explicitly every transaction, even those started by Django or by third-party libraries. Thus, this is best used in situations where you want to run your own transaction-controlling middleware or do something really strange.
所以不要那样做。 Django 当然会为该原子块禁用自动提交并在块完成时重新启用它。
我有一个简单的图书馆应用程序。为了强制将 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")
关于这个,我还遗漏了什么吗?我在 Python 3.4.3 中使用 Django 1.9,数据库是 MySQL.
您正确使用了 transaction.atomic()
(包括将 try ... except
置于交易之外),但您绝对不应该设置 AUTOCOMMIT = False
.
作为 documentation states, you set that system-wide setting to False
when you want to "disable Django’s transaction management"—but that's clearly not what you want to do, since you're using transaction.atomic()
! More from the documentation:
If you do this, Django won’t enable autocommit, and won’t perform any commits. You’ll get the regular behavior of the underlying database library. This requires you to commit explicitly every transaction, even those started by Django or by third-party libraries. Thus, this is best used in situations where you want to run your own transaction-controlling middleware or do something really strange.
所以不要那样做。 Django 当然会为该原子块禁用自动提交并在块完成时重新启用它。