django類視圖簡單使用和源碼解析
django的類視圖,CBV:
我們在開始接觸django的時候,習慣於使用函數編寫視圖,即FBV。使用FBV時,我們只需要在路由匹配時,對應的路由下找到這個函數就可以了,這樣做看似很和諧,但是有的時候,譬如說,當我們需要根據同一個url請求方法的不同而去執行不同的操作時,如果使用FBV去編寫視圖,那麽我們就需要在視圖函數中不斷地去執行if request.method==‘請求方法‘ 去判斷要去執行什麽內容,此時的代碼就顯得不是很優雅。但是此時如果我們使用CBV的方式來編寫視圖,同樣的需求,代碼就會顯得優雅很多,下面就讓我來介紹一下CBV的具體實現:
在django中使用CBV編寫視圖:
1、首先我們自定義的視圖類需要繼承django.views.View類
2、在視圖類中定義以‘請求方法名稱小‘寫為名稱的方法,這樣在執行不同的請求方法的時候就回去自動執行對應的函數
3、在路由映射的時候,要執行這個試圖類的as_view()方法,註意這個方法繼承自django.views.View
示例代碼如下:
‘views.py‘文件:
from django.views import View
from django.http import HttpResponse
class UserInfoView(View):
def get(self, request, *args, **kwargs):
return HttpResponse(‘get user‘)
def post(self, request, *args, **kwargs):
return HttpResponse(‘post user‘)
def delete(self, request, *args, **kwargs):
return HttpResponse(‘delete user‘)
‘url.py‘文件
from app import views
urlpatterns = [
path(‘user/‘, views.UserInfoView.as_view())
]
上述示例代碼就可以根據同一個url執行不同的方法時去執行不同的操作
CBV實現的源碼分析:
1、請求進來,路由找到試圖類並執行as_view方法,執行這個方法時其實會返回一個view函數,因此可以看做請求進來之後會先執行試圖類的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):
self = cls(**initkwargs)
if hasattr(self, ‘get‘) and not hasattr(self, ‘head‘):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
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
2、從上面的源碼中可以看出執行view方法,實際上就是返回self.dispatch方法,也就是說會去執行self.dispatch方法
3、因為試圖類本身沒有定義dispatch方法,那麽在執行dispatch方法的時候就需要去其父類裏面查找,而父類裏面的dispatch方法則會根據請求方法的不同基於python類的反射去找到相應的方法,然後執行,這樣就會自動實現根據請求方法的不同去執行不同的內容了,dispatch方法的源碼如下:
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)
django類視圖簡單使用和源碼解析