django 类通用视图详解
view() :
该类为所有类视图的父类,处于最底层,仅仅只对请求参数做校验后,给特定请求方法做特定调用。
用法:
url中定位到类方法:Aa.as_view() ——> View.as_view()方法对请求参数做判断后,转到View.dispatch() ——> 找到Aa.get() 或者Aa.post() 或者Aa.其他请求方法 ———>处理完成后返回view()
需要对请求方式做特定处理,可以自行修改dispatch()方法。
源码:
class View(object): """ Intentionally simple parent class for all views. Only implements dispatch-by-method and simple sanity checking. 该视图为所有类视图的父类,处于最底层,仅仅只实现了给特定的请求方式 进行特定方法的调度 """ # http 所有请求方式的列表 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] def __init__(self, **kwargs): """ Constructor. Called in the URLconf; can contain helpful extra keyword arguments, and other things. # 构造函数接收键值对参数,该参数来源于 URLconf配置中的传递 """ # Go through keyword arguments, and either save their values to our # instance, or raise an error. # 接收关键字参数,并将其添加到实例中或者引发错误 for key, value in six.iteritems(kwargs): setattr(self, key, value) @classonlymethod def as_view(cls, **initkwargs): """ # as_view 是一个闭包,做了一些校验工作后,再返回view函数 Main entry point for a request-response process. """ for key in initkwargs: #as_view()方法中,如果传递的关键字参数key为默认的http 请求方法,则报错, #默认不允许使用http请求方法作为参数 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__)) # as_view()方法中,如果传递过来的参数key 不在as_view()的属性中,也报错 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)) # view 方法作用是给请求对象添加三个参数,调用dispatch方法处理请求 def view(request, *args, **kwargs): # 作用:增加属性,调用dispatch方法 self = cls(**initkwargs) # 调用as_view 父类,创建一个实例对象 # 如果对象中有get属性,或者没有head属性,就创建head属性 if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get # 为对象创建request、args和kwargs 三个属性 self.request = request self.args = args self.kwargs = kwargs #调用dispatch 函数找到指定的请求方法, return self.dispatch(request, *args, **kwargs) view.view_class = cls view.view_initkwargs = initkwargs # take name and docstring from class update_wrapper(view, cls, updated=()) # and possible attributes set by decorators # like csrf_exempt from dispatch update_wrapper(view, cls.dispatch, assigned=()) return view # 找到请求的方法,执行该方法 def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. # 找到请求的方法,如果请求方法不在允许的列表中或者请求方法不存在就按照错误处理 # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] # 如果请求方法存在,则取出该方法 if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) # 如果不存在则报405错误 else: handler = self.http_method_not_allowed # 执行该请求方法 return handler(request, *args, **kwargs) 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 http.HttpResponseNotAllowed(self._allowed_methods()) def options(self, request, *args, **kwargs): """ Handles responding to requests for the OPTIONS HTTP verb. """ response = http.HttpResponse() response['Allow'] = ', '.join(self._allowed_methods()) response['Content-Length'] = '0' return response def _allowed_methods(self): return [m.upper() for m in self.http_method_names if hasattr(self, m)]
用法实例:
class LoginUserView(View): def dispatch(self, request, *args, **kwargs): print "进入了改写后的dispatch方法" discontext = super(LoginUserView, self).dispatch(request, *args, **kwargs) print "没有改变调用请求方式,直接返回原始dispatch调用" return discontext def post(self, request): context = userservice.login_user(request=request) return JsonResponse(context)
ListView() :
请查看新博客:www.vhosts.cn