当启用ATOMIC_REQUESTS
时,每个 View 都包装在一个事务中。如果 View 引发异常,事务就会回滚,这很方便。问题是,您必须允许异常传播通过 View ,并且您将得到 HTTP 500 结果。
因此,要利用ATOMIC_REQUESTS
,我们认为有必要用我们自己的实现覆盖handler500
,这将检查导致错误的异常并提供正常的用户友好的HTTP 200在适当的情况下响应,否则回退到默认响应,即 Debug模式下的堆栈跟踪或默认的 Django handler500。
例如
class UserFriendlyError(Exception):
pass
def my_view(request):
# Do some database work here...
if request.GET['foo'] == 'bar': # Some condition
# The idea is to show this to user. my_custom_handler500 would handle this
raise UserFriendlyError("Don't do this, this is deprecated -- do that instead")
# Normal exceptions can happen too and would provide a real HTTP 500 instead
# ...
def my_custom_500(request):
ex = sys.exc_info()[1]
if isinstance(ex, UserFriendlyError):
# Return a normal 200 response
return render(request, 'user_friendly_error.html', {'exception': ex})
# Otherwise fall back to the default handler
return django.views.defaults.server_error(request)
参见this question了解更多背景。
问题是,当DEBUG
模式处于事件状态时,handler500
机器是circumvented with the stack trace debug handler 。但是,要实现此功能,仍应在 DEBUG
模式下调用自定义 500 处理程序,但回退到调试堆栈跟踪处理程序而不是默认的 500 处理程序。
有没有办法让它工作,最好不破坏 Django 的功能?或者也许有更好的方法来做同样的事情,不是吗?
最佳答案
实现您自己的中间件似乎是一条出路。只需将其放在 MIDDLEWARE_CLASSES
列表的末尾并实现 process_exception其中,例如
class MyMiddleware(object):
"""Handles UserFriendlyError"""
def process_exception(self, request, exception):
if isinstance(exception, UserFriendlyError):
return render(request, 'user_friendly_error.html', {'exception': exception})
else:
return None
# In your settings.py
MIDDLEWARE_CLASSES = (
# ...
'myproject.mymiddleware.MyMiddleware',
)
只有七行代码,无论 DEBUG
模式如何,都可以按预期工作,并且根本不需要修改 500 处理程序。
关于python - 通过处理 500 处理程序中的一些错误并在这些情况下呈现正常的 HTTP 响应来明智地利用 ATOMIC_REQUESTS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21138218/