Django 1.10:在主事务失败/回滚后将数据提交到日志表

时间:2017-01-20 19:08:26

标签: django transactions

我从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建议不要这样做:“这最适用于你想要运行自己的事务控制中间件或做一些非常奇怪的事情的情况。”

2 个答案:

答案 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