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() :