django的類視圖擁有自動(dòng)查找指定方法的功能, 通過調(diào)用是通過as_view()方法實(shí)現(xiàn)
urls.py
from meduo_mall.demo import views
urlpatterns = [
url(r'register/$', views.Demo.as_view())
]
views.py
from django.views.generic import View
class Demo(View):
def get(self, request):
return HttpResponse('get page')
def post(self, request):
return HttpResponse('post page')
為什么as_view能自動(dòng)匹配指定的方法,
先看源碼
@classonlymethod
def as_view(cls, **initkwargs): # 實(shí)際上是一個(gè)閉包 返回 view函數(shù)
"""
Main entry point for a request-response process.
"""
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): # 作用:增加屬性, 調(diào)用dispatch方法
self = cls(**initkwargs) # 創(chuàng)建一個(gè) cls 的實(shí)例對(duì)象, cls 是調(diào)用這個(gè)方法的 類(Demo)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request # 為對(duì)象增加 request, args, kwargs 三個(gè)屬性
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs) # 找到指定的請(qǐng)求方法, 并調(diào)用它
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,
if request.method.lower() in self.http_method_names: # 判斷請(qǐng)求的方法類視圖是否擁有, http_method_names=['get', 'post']
handler = getattr(self, request.method.lower(), self.http_method_not_allowed) # 如果存在 取出該方法
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 執(zhí)行該方法
簡(jiǎn)化版
@classonlymethod
def as_view(cls, **initkwargs): # 實(shí)際上是一個(gè)閉包 返回 view函數(shù)
"""
Main entry point for a request-response process.
"""
def view(request, *args, **kwargs): # 作用:增加屬性, 調(diào)用dispatch方法
self = cls(**initkwargs) # 創(chuàng)建一個(gè) cls 的實(shí)例對(duì)象, cls 是調(diào)用這個(gè)方法的 類(Demo)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request # 為對(duì)象增加 request, args, kwargs 三個(gè)屬性
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs) # 找到指定的請(qǐng)求方法, 并調(diào)用它
return view
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
if request.method.lower() in self.http_method_names: # 判斷請(qǐng)求的方法類視圖是否擁有, http_method_names=['get', 'post']
handler = getattr(self, request.method.lower(), self.http_method_not_allowed) # 如果存在 取出該方法
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 返回該請(qǐng)求方法執(zhí)行的結(jié)果
再簡(jiǎn)化
def as_view(): # 校驗(yàn) + 返回view方法
# 一些校驗(yàn)
...
def view(): # 執(zhí)行視圖
# 增加 為對(duì)象request, args, kwargs 屬性
...
return dispatch() # 調(diào)用指定的請(qǐng)求方法
return view
def dispatch(): # 真正的查找指定的方法, 并調(diào)用該方法
...
return handler()
調(diào)用順序: as_view --> view --> dispatch
可以看出
as_view實(shí)際上是一個(gè)閉包, 它的作用做一些校驗(yàn)工作, 再返回view方法.而
view方法的作用是給請(qǐng)求對(duì)象補(bǔ)充三個(gè)參數(shù), 并調(diào)用dispatch方法處理dispatch方法查找到指定的請(qǐng)求方法, 并執(zhí)行
可以得出結(jié)論: 實(shí)際上真正實(shí)現(xiàn)查找的方法是 dispatch方法