class View:
def http_method_not_allowed(self, request, *args, **kwargs):
logger.warning(
'Method Not Allowed (%s): %s', request.method, request.path,
extra={'status_code': 405, 'request': request}
)
return HttpResponseNotAllowed(self._allowed_methods())
比如当一个类视图函数之定义了 get 方法,而没有定义 post 方法,那么这个类视图函数接收到 post 的请求的时候,由于找不到相对应的 post 的定义,就会通过另一个方法 dispatch 分发到 http_method_not_allowed 方法中。
class View:
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
http_method_names 定义当前 View可以接受的请求类型:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']首先,if 判断当前的请求类型是否可以被接受,即请求方是否定义在 http_method_names 变量中。若能够接受请求,则 dispatch() 尝试获取 View 中的同名方法,如果不存在,则将 handler 指定为 http_method_not_allowed 即不被允许的方法。然后 else 规定如果方法不被接受则直接将其指定为 http_method_not_allowed。
@classonlymethod装饰器,作用是只允许类对象调用这个方法,如果是类实例调用,将会抛出 AttributeError 异常。该方法的源码如下所示:
class View:
@classonlymethod
def as_view(cls, **initkwargs):
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
def view(request, *args, **kwargs):
#创建View类实例
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.setup(request, *args, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
#调用View实例的dispatch方法
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
update_wrapper(view, cls, updated=())
update_wrapper(view, cls.dispatch, assigned=())
return view
Django 将一个 HTTP 请求映射到一个可调用的函数,而不是一个类对象。所以,在定义 URL 路由的时候总是需要调用 View 的 as_view 方法。可以看到,上述的as_view 方法,它创建了 View 类的实例,然后调用了 dispatch 方法,根据请求类型分发处理请求函数。
版权说明:Copyright © 广州松河信息科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州松河信息科技有限公司 版权所有