Django - 使用事务原子回滚保存
Django - Rollback save with transaction atomic
我正在尝试创建一个用于保存对象的视图,但如果出现某些异常,我想撤消 保存。这是我试过的:
class MyView(View):
@transaction.atomic
def post(self, request, *args, **kwargs):
try:
some_object = SomeModel(...)
some_object.save()
if something:
raise exception.NotAcceptable()
# When the workflow comes into this condition, I think the previous save should be undone
# What am I missing?
except exception.NotAcceptable, e:
# do something
我做错了什么?即使引发异常 some_object
仍在数据库中。
但是,如果用transaction.atomic装饰的函数发生了异常,那你就没事了,它会rollback automatically to the savepoint created by the decorator before running the your function, as documented:
atomic allows us to create a block of code within which the atomicity on the database is guaranteed. If the block of code is successfully completed, the changes are committed to the database. If there is an exception, the changes are rolled back.
如果异常在 except 块中被捕获,那么 atomic 应该 re-raised 捕获它并执行回滚,即:
try:
some_object = SomeModel(...)
some_object.save()
if something:
raise exception.NotAcceptable()
# When the workflow comes into this condition, I think the previous save should be undome
# Whant am I missing?
except exception.NotAcceptable, e:
# do something
raise # re-raise the exception to make transaction.atomic rollback
另外,如果你想要更多的控制,你可以手动回滚到previously set savepoint,即:
class MyView(View):
def post(self, request, *args, **kwargs):
sid = transaction.savepoint()
some_object = SomeModel(...)
some_object.save()
if something:
transaction.savepoint_rollback(sid)
else:
try:
# In worst case scenario, this might fail too
transaction.savepoint_commit(sid)
except IntegrityError:
transaction.savepoint_rollback(sid)
总而言之,如果您的视图生成没有错误的响应,@transaction.atomic
将在数据库上执行事务。因为您自己捕获了异常,所以在 Django 看来您的视图执行得很好。
如果捕获到异常,需要自己处理:Controlling Transactions
如果您需要在失败时生成正确的 json 响应:
from django.db import SomeError, transaction
def viewfunc(request):
do_something()
try:
with transaction.atomic():
thing_that_might_fail()
except SomeError:
handle_exception()
render_response()
对我来说,这适用于 Django 2.2.5
首先在你的settings.py
...
DATABASES = {
'default': {
'ENGINE': 'xxx', # transactional db
...
'ATOMIC_REQUESTS': True,
}
}
在你的函数中 (views.py)
from django.db import transaction
@transaction.atomic
def make_db_stuff():
# do stuff in your db (inserts or whatever)
if success:
return True
else:
transaction.set_rollback(True)
return False
我正在尝试创建一个用于保存对象的视图,但如果出现某些异常,我想撤消 保存。这是我试过的:
class MyView(View):
@transaction.atomic
def post(self, request, *args, **kwargs):
try:
some_object = SomeModel(...)
some_object.save()
if something:
raise exception.NotAcceptable()
# When the workflow comes into this condition, I think the previous save should be undone
# What am I missing?
except exception.NotAcceptable, e:
# do something
我做错了什么?即使引发异常 some_object
仍在数据库中。
但是,如果用transaction.atomic装饰的函数发生了异常,那你就没事了,它会rollback automatically to the savepoint created by the decorator before running the your function, as documented:
atomic allows us to create a block of code within which the atomicity on the database is guaranteed. If the block of code is successfully completed, the changes are committed to the database. If there is an exception, the changes are rolled back.
如果异常在 except 块中被捕获,那么 atomic 应该 re-raised 捕获它并执行回滚,即:
try:
some_object = SomeModel(...)
some_object.save()
if something:
raise exception.NotAcceptable()
# When the workflow comes into this condition, I think the previous save should be undome
# Whant am I missing?
except exception.NotAcceptable, e:
# do something
raise # re-raise the exception to make transaction.atomic rollback
另外,如果你想要更多的控制,你可以手动回滚到previously set savepoint,即:
class MyView(View):
def post(self, request, *args, **kwargs):
sid = transaction.savepoint()
some_object = SomeModel(...)
some_object.save()
if something:
transaction.savepoint_rollback(sid)
else:
try:
# In worst case scenario, this might fail too
transaction.savepoint_commit(sid)
except IntegrityError:
transaction.savepoint_rollback(sid)
总而言之,如果您的视图生成没有错误的响应,@transaction.atomic
将在数据库上执行事务。因为您自己捕获了异常,所以在 Django 看来您的视图执行得很好。
如果捕获到异常,需要自己处理:Controlling Transactions
如果您需要在失败时生成正确的 json 响应:
from django.db import SomeError, transaction
def viewfunc(request):
do_something()
try:
with transaction.atomic():
thing_that_might_fail()
except SomeError:
handle_exception()
render_response()
对我来说,这适用于 Django 2.2.5
首先在你的settings.py
...
DATABASES = {
'default': {
'ENGINE': 'xxx', # transactional db
...
'ATOMIC_REQUESTS': True,
}
}
在你的函数中 (views.py)
from django.db import transaction
@transaction.atomic
def make_db_stuff():
# do stuff in your db (inserts or whatever)
if success:
return True
else:
transaction.set_rollback(True)
return False