我从Django 1.5迁移到Django 1.10并发现数据库事务与提交和回滚控制很少有差别。
我想要的是什么:
Perform series of queries in view: my_function(request)
If all queries succeed:
commit
if any query fails:
rollback
insert into log table and commit the insertion
在Django 1.5中,我使用异常中间件中的回滚和提交来处理这个问题:
class ExceptionMiddleware(object):
def process_exception(self, request, exception):
# do rollback
# insert into log table
# commit
我怎样才能在Django 1.10中实现这一点,那里似乎没有办法进行回滚?
我的1.10设置:
AUTOCOMMIT = True
ATOMIC_REQUESTS = True
这会将所有查询放入一个事务中,正确地,只在完成时提交。
我将使用“AUTOCOMMIT = False”进行更多的回滚/提交控制,但Django建议不要这样做:“这最适用于你想要运行自己的事务控制中间件或做一些非常奇怪的事情的情况。”
答案 0 :(得分:2)
Django 1.10还引入了一种新型的中间件,这使得这很容易:
from django.db import transaction
class LoggingMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
with transaction.atomic():
response = self.get_response(request)
except:
log_failure()
raise
return response
当通过__exit__
的{{1}}方法传播异常时,事务会自动回滚。然后,您可以捕获异常并将失败记录在封装视图的主事务之外。
答案 1 :(得分:1)
以下工作。当my_view()中存在异常时,会回滚其插入,但会提交异常中间件中的插入。
settings.py
Database ATOMIC_REQUESTS = True
MIDDLEWARE = [
...
'myproject.middleware.ExceptionMiddleware', # put it last
]
views.py
def my_view(request):
do table insertion insertion..
x = 1/0 # cause exception
middleware.py
from django.utils.deprecation import MiddlewareMixin
class ExceptionMiddleware(MiddlewareMixin):
def process_exception(self, request, exception):
# can be put inside "with transaction.atomic():" for more control of rollback/commit within this function
log_error() # do table insertion
# can return some response