前言:Django的視圖處理方式有兩種:
- FBV(function base views) 是在視圖里基于函數(shù)形式處理請求。
- CBV(class base views)是在視圖里基于類的形式處理請求。
Python是一個面向對象的編程語言,如果只用函數(shù)來開發(fā),有很多面向對象的優(yōu)點就錯失了(繼承、封裝、多態(tài))。所以Django在后來加入了Class-Based-View??梢宰屛覀冇妙悓慥iew。這樣做的優(yōu)點主要下面兩種:
- 提高了代碼的復用性,可以使用面向對象的技術,比如Mixin(多繼承)
- 可以用不同的函數(shù)針對不同的HTTP方法處理,而不是通過很多if判斷,提高代碼可讀性
那下面我們來看一下django的源碼,從而進一步了解Django的CBV
一、首先看url:
url:
url(r'register/$',views.Register.as_view())
django的CBV在url中的書寫需要在view.類名后加.as_view(),從中可以了解到as_view一定是一個方法,這個方法加上了(),是在Django項目啟動時就自動執(zhí)行的,返回值也應該是 一個函數(shù)名,從而在匹配url后可以執(zhí)行相應的函數(shù)
PS:關于分析源碼的首要任務是需要清楚方法的調用者和self的歸屬類?。。『苤匾?br> view.py:
class Register(View):
def get(self,request):
return render(request, 'register.html')
源碼:
@classonlymethod
def as_view(cls, **initkwargs):
pass
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)
return view
源碼執(zhí)行簡易流程圖:

1.png
到此可以很明顯的看出,Django項目啟動后,CBV下的url執(zhí)行后相當于:
url(r'register/$',views.Register.view)
二、接下來當有用戶訪問url時,對應url的view會執(zhí)行對應請求方式下的類方法
源碼:以下源碼注意兩點 1. cls涉及到了----《閉包作用域 》; 2. self的指向
@classonlymethod
def as_view(cls, **initkwargs):
pass
def view(request, *args, **kwargs):
self = cls(**initkwargs) //cls是Register類,self是實例化的對象
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)
return view
view.py: 找dispatch方法時需要先找自己類中,沒有再找繼承類中
class Register(View):
def get(self,request):
return render(request, 'register.html'))
源碼: 執(zhí)行對應的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)

7.png