我正在编写多个视图,并希望验证请求正文。常见的情况是主体必须是存在某些键的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")
InvalidInputResponse
是http.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中是否有等效的机制?如果没有相应的机制,那么处理这个问题的方法是什么?
答案 0 :(得分:2)
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
猴子修补程序来完成这项工作:
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