【问题标题】:Django transaction rollback on HTTP error responsesDjango 事务回滚 HTTP 错误响应
【发布时间】:2012-11-28 17:03:49
【问题描述】:

如果视图代码抛出异常,所有django transaction stuff 都会回滚事务。如果我返回带有错误状态代码的 HttpResponse(即 4xx 或 5xx),如何让它回滚?

【问题讨论】:

    标签: django orm transactions decorator httpresponse


    【解决方案1】:

    好吧,我根本没有测试过这个,我不知道它是否正确,但这样的事情可能会奏效。如有任何反馈,我将不胜感激!

    from functools import wraps
    from django.utils.decorators import available_attrs
    from django.db import transaction
    from django.http import HttpResponse
    
    def commit_on_http_success(function=None, using=None, successStatuses=[200]):
        """Like commit_on_success, but rolls back the commit if we return an HttpResponse
        with a status that isn't 200 (by default).
    
        Args:
            using: The database to use. Uses the default if None.
            successStatuses: The HTTP statuses for which we will commit the transaction.
        Raises:
            It can raise an exception that overrides the view's exception if commit() or
            rollback() fails.
        """
    
        def decorator(view_func):
            @wraps(view_func, assigned=available_attrs(view_func))
            def _wrapped_view(request, *args, **kwargs):
                try:
                    transaction.enter_transaction_management(using=using)
                    transaction.managed(True, using=using)
    
                    exc = None
                    commit = False
                    try:
                        response = view_func(request, *args, **kwargs)
                        if isinstance(response, HttpResponse) and response.status in successStatuses:
                            commit = True
                    except Exception, exc:
                        pass
    
                    if transaction.is_dirty(using=using):
                        if commit:
                            try:
                                transaction.commit(using=using)
                            except:
                                transaction.rollback(using=using)
                                raise
                        else:
                            transaction.rollback(using=using)
                finally:
                    transaction.leave_transaction_management(using=using)
    
                if exc is not None:
                    raise exc
    
                return response
            return _wrapped_view
    
        if function:
            return decorator(function)
        return decorator
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 1970-01-01
      • 2011-01-10
      • 1970-01-01
      • 2013-05-17
      • 1970-01-01
      相关资源
      最近更新 更多