1. 程式人生 > >Django CBV流程及原始碼分析

Django CBV流程及原始碼分析

       Django 實現檢視的方法有兩種,一種是FBV(function base view)即基於函式的檢視,還一種高階的就是CBV(class base view),通過閱讀原始碼你會發現它本質上還是基於FBV的。FBV的優點是用法和寫法都比較簡單適合剛開始學的同學使用,缺點就是不能用的面向物件的幾大特性只用函式進行封裝程式碼多的時候會顯得程式碼很冗餘,而CBV就很好的解決了這些問題。並且Django官方在後面的Django版本中加入了很多基於CBV的類,方便我們快速開發。我們先簡單的看下Django在中路由規則的是怎麼定義的,再粗略的看下一FBV,然後再講下我們今天的重點CBV。

  1、Django中路由規則的定義,沒有仔細讀原始碼,簡單的講一下

    從這裡進入url的定義:

      

   這是原始碼

      

   從原始碼可以看出,我們在定義路由規則時,第一個引數應該傳入一個正則表示式,第二個引數傳入的就是view,從下面的處理邏輯看,view的型別可以用兩種。第一種是list 或tuple但這種是用來處理include(......)匯入的url的,第二種型別就是callable型別的也就是可執行的即函式所以我們在寫FBV的時候一定不要寫上帶上括號,因為url()函式需要的是一個可執行物件。如果傳入這兩種以外的型別就會報錯。我們知道其實include匯入 的其實也是一個callable型別的。所以我們可以確定view本質上傳入的是一個可執行的物件,在啟動服務時程式讀取路由將view函式載入記憶體,接受到請求的時候就會執行這view函式並且返回資料。

理解這一點很重要,這個是FBV和CBV的基礎。  

  2、FBV中檢視的定義和url的寫法

   FBV(基於函式的檢視),定義一個函式根據請求方法的不同而作出相應的處理,注意重點是將對請求的處理封裝在一個函式中。看下例子

   view.py

   

   定義了一個login函式通過判斷請求的方法進行返回

   url.py

        

   將app01中的views檔案匯入並將login方法傳給url實現了一個FBV

   3、CBV中檢視的定義和url的寫法

   CBV(基於類的檢視),定義一個類,繼承django.views.View,將處理各種請求方式的邏輯用方法名加處理邏輯封裝在方法裡面,注意重點是將請求的處理封裝在類裡面

    eg:

           form dajngo.views import VIew

           class Cbv(View):

                  def a(self, params):
        pass

                  def b(self, params):

                        pass

      def get(self, request, *args, **kwargs):

        pass

                  def post(self, request, *args, **kwargs):

        pass

      def put(self, request, *args, **kwargs):

        pass       

   看下例子:

    view.py  檢視的定義

      

   url.py  路由的寫法

      

  4、分析3中的呼叫過程

在Django專案啟動時路由規則開始載入記憶體當程式讀到url(r'^cbv/', views.Cbv.as_View())時重點來了,views.Cbv是我們自己定義的一個物件當我們.as_view()的時候就執行了父類的靜態函式as_view方法(根據面向物件的特性可以知道是呼叫的父類的),我們可以根據在1中得出的結論.as_view()返回的一定是個可呼叫物件

看下原始碼中as_view函式的定義:

  

可以看到,as_view方法正如我們想的那樣返回的是個可呼叫物件view,在路由規則載入記憶體後.as_view的到的其實是個view方法,在接受到請求是才會執行view方法,而view方法的返回值是self.dispatch(request, *args, **kwargs),是由一個例項物件呼叫的dispatch方法,我們怎麼這個self是誰呢?我們可以一層一層的往上拔從而確定這個例項物件是誰。

self.dispatch(request, *args, **kwargs)是由view()方法呼叫的,view()方法又是由as_view()方法呼叫的,as_view()方法又是由views.Cbv呼叫的,所以我們可以確定self就是Cbv的例項物件,但我們沒有定義dispatch方法所以這個dispatch方法一定在Views類中有定義。

  

這就是父類中dispatch的定義,先判斷請求是否正確,以get請求為例如果請求正確的話就就利用反射到self中去找與請求方式相對應的方法,根據我們上面的分析self就是我們定義的類Cbv,handler就是我們定義的get方法最後return 我們定義的get方法的返回值。一層一層的向上冒泡,get方法將返回值給dispatch,dispatchs再將返回值給view,到了view這層就和FBV一樣了。