view() :python
該類爲全部類視圖的父類,處於最底層,僅僅只對請求參數作校驗後,給特定請求方法作特定調用。
閉包
用法:app
url中定位到類方法:Aa.as_view() ——> View.as_view()方法對請求參數作判斷後,轉到View.dispatch() ——> 找到Aa.get() 或者Aa.post() 或者Aa.其餘請求方法 ———>處理完成後返回view()函數
須要對請求方式作特定處理,能夠自行修改dispatch()方法。post
源碼:url
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)]
用法實例: spa
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() :code