Django中CBV檢視的原始碼分析
前言:Django的檢視處理方式有兩種:
- FBV(function base views) 是在視圖裡基於函式形式處理請求。
- CBV(class base views) 是在視圖裡基於類的形式處理請求。
Python是一個面向物件的程式語言,如果只用函式來開發,有很多面向物件的優點就錯失了(繼承、封裝、多型)。所以Django在後來加入了Class-Based-View。可以讓我們用類寫View。這樣做的優點主要下面兩種:
- 提高了程式碼的複用性,可以使用面嚮物件的技術,比如Mixin(多繼承)
- 可以用不同的函式針對不同的HTTP方法處理,而不是通過很多if判斷,提高程式碼可讀性
那下面我們來看一下django的原始碼,從而進一步瞭解Django的CBV
一、首先看url:
url:
url(r'register/$',views.Register.as_view())
django的CBV在url中的書寫需要在 view.類名 後加 .as_view() ,從中可以瞭解到as_view一定是一個方法,這個方法加上了(),是在Django專案啟動時就自動執行的,返回值也應該是 一個函式名,從而在匹配url後可以執行相應的函式
PS:關於分析原始碼的首要任務是需要清楚 方法的呼叫者 和 self 的歸屬類!!!很重要
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
原始碼執行簡易流程圖:

1.png
到此可以很明顯的看出,Django專案啟動後,CBV下的url執行後相當於:
url(r'register/$',views.Register.view)
二、接下來當有使用者訪問url時,對應url的view會執行對應請求方式下的類方法
原始碼:以下原始碼注意兩點 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'))
原始碼:執行對應的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
到此Django基於CBV的原始碼執行流程就結束了,很好的利用了python面向物件的三大特性:繼承、封裝和多型。看完原始碼,是不是感覺python的面向物件有時候用起來意猶未盡。。。。。