【问题标题】:Is there an equivalent of Flask's `@app.errorhandler` in Django?Django 中是否有 Flask 的 `@app.errorhandler` 等价物?
【发布时间】:2016-06-02 17:31:29
【问题描述】:

我正在编写几个视图,并希望验证请求正文。常见的情况是主体必须是具有某些键的 JSON 对象。我写了一个视图,并且有这个代码:

try:
    body = json.loads(request.body)
except ValueError:
    return InvalidInputResponse("Could not load request body")

if not isinstance(body, dict):
    return InvalidInputResponse("Request body was not a JSON object")

if set(body.keys()) != {'author', 'title', 'content'}:
    return InvalidInputResponse("Request object missing keys")

InvalidInputResponsehttp.HttpResponse 的子类。

我想在其他视图中重复使用此代码。我真正想做的是:

body = process_body(request.body, required_keys={'author', 'title', 'content'})
# rest of code here ...

但是,按照现在的代码,我不能这样做。我必须这样做:

body = process_body(request.body, required_keys={'author', 'title', 'content'})
if isinstance(body, http.HttpResponse):
    return body
# rest of code here ...

这有点难看。

在 Flask 中,我可以创建一个自定义异常,称为 InvalidInputException,然后是 register an error handler for it... 比如说:

@app.errorhandler(InvalidInputException)
def handle_invalid_input(error):
    return InvalidInputResponse(error.reason)

Django 中是否有等效机制?如果没有等效的机制,那么等效的处理方式是什么?

【问题讨论】:

标签: python django error-handling flask


【解决方案1】:

Django 也有自定义异常处理程序。它们可以附加via middleware

class InvalidInputMiddleware(object):
    def process_exception(self, request, exception):
        if isinstance(exception, InvalidInputException):
             return InvalidInputResponse(exception.reason)

        return None

Django 将返回任何中间件返回的第一个响应。请注意,响应阶段以相反的顺序运行中间件。

如果全局使用,只需添加到MIDDLEWARE_CLASSES 的末尾即可。对于非全局情况,我使用(有点邪恶)middleware_on_class monkey-patcher 来完成这项工作:

from functools import wraps
from django.utils.decorators import (
    decorator_from_middleware,
    method_decorator
)

def middleware_on_class(middleware):
    def decorator(cls):
        dispatch = cls.dispatch

        @wraps(dispatch)
        @method_decorator(decorator_from_middleware(middleware))
        def wrapper(self, *args, **kwargs):
            return dispatch(self, *args, **kwargs)

        cls.dispatch = wrapper
        return cls
    return decorator

用作

handle_invalid_input = middleware_on_class(InvalidInputMiddleware)

@handle_invalid_input
class View(...):
    pass

【讨论】:

  • 啊好吧!我理解全球方法。你能解释一下我如何使用middleware_on_class吗?我对 Django 还不够熟悉,无法了解如何应用它。
  • @Claudiu 已添加。请注意,这是我的典型用例 YMMV。
猜你喜欢
  • 1970-01-01
  • 2010-12-20
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 2013-06-21
  • 2014-01-09
  • 2012-02-18
相关资源
最近更新 更多