前言
最近學習了 django 的一個 restframework 框架,對于里面的執行流程產生了興趣,經過昨天一晚上初步搞清楚了執行流程(部分方法還不太清楚),于是想詳細的總結一下當來一個請求時,在該框架里面是如何執行的?
啟動項目時
昨天在調試django時,發現在 apiview 中打的斷點沒有斷下來,而是打在 view 中的斷點斷下來了,調試了很多次,最后發現,在 django 項目啟動時,會首先加載 urls 中的文件,執行 views 中類的 as_view方法,其實是繼承自 apiview 的,apiview 繼承自 django 原生 view 的as_view 方法。
里面一個參數叫 pattern_name,對應的值是admin:auth_group_change,如下圖所示:
目前還不清楚這里面的具體流程是什么,但是并不妨礙閱讀之后的源碼,在這只要清楚一點,在 django 項目啟動時,路由所對應的cbv里面的相關方法的內存地址已經獲取到。這樣做的好處就是提高效率,壞處可能有一點點,會提升性能的消耗。
具體路由和邏輯代碼
在這里假設來一個 get 請求,urls 和 views里面的代碼如下:
1
2
3
|
# urls.py url(r '^book/(?p<id>\d+)/' , views.book.as_view()), |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# views.py class book(apiview): def dispatch( self , request, * args, * * kwargs): return super ().dispatch(request, * args, * * kwargs) def get( self , request, id ): response = { 'status' : 100 , 'msg' : none} book = models.book.objects. filter (pk = id ).first() book_ser = bookserib(book, many = false) print ( 'book_ser.data' , book_ser.data) response[ 'books' ] = book_ser.data response[ 'msg' ] = '獲取圖書成功' print ( 'response' , response) return response(response) |
urls 里面就是一個典型的 cbv 的路由配置,在 views 中一個是路由分發方法,一個是獲取單本圖書信息(通過 id)。
as_view 具體執行流程
在項目啟動時,相應的函數內存地址已經獲取到,那么具體是怎么獲取到的呢?
在上面的代碼中可以看到 book
類是繼承自 apiview
類的,所以在路由配置里面執行的 as_view
方法如果 book
類沒有重寫,那么執行的就是按照 mro
列表順序查找到的第一個方法,在這里執行的是 apiview
類中的 as_view
方法。
查看該源碼如下:
apiview
類的父類是 view
類,查看該類的 as_view
方法,源碼如下:
具體 as_view
就是將 view
函數的內存地址返回,以便請求來時直接調用。
而 initkwargs
這個參數應該是由 django 內部傳的一些參數,如下所示:
請求到來時
因為經過 django 先執行了 as_view
返回 view
的內存地址,所以會直接執行 view
函數,如下:
在這里該 self 由于是 繼承自 apiview
類的 book
類的對象,所以 dispatch
方法首先去自身找,之后去父類找,在 apiview
類中找到 dispatch
方法,源碼如下:
initialize_request方法:
源碼如下:
在實例化 request
對象時, authenticators
參數需要在認證時使用,所以先把這個參數的值找出來。步驟如下:
調用 self.get_authenticators
找到 self.authentication_classes
找到 api_settings,才能找到default_authentication_classes
default和import_strings參數
default參數
import_strings參數
實例化 apisettings 對象
通過__getattr__方法獲取值
執行perform_import方法
執行import_from_string
執行import_module
執行_bootstrap._gcd_import
執行_sanity_check
_sanity_check返回,執行_find_and_load方法
所以通過__getattr__的到的是一個列表,里面是兩個類,分別是[rest_framework_authentication_sessionauthentication, rest_framework_authentication_basicauthentication]
到這里,initialize_request方法執行結束,得到一個經過 request 類實例化的 request 對象,該對象里面含有原生 request 對象,可以通過 request._request
取到。
initial 方法:
源碼如下:
這里傳入的 request
參數是經過 request
封裝后的參數
執行get_format_suffix
執行完這個方法, self_format_kwarg = none
,
執行perform_content_negotiation
執行self.get_renders
執行self.get_content_negotiator
執行 conneg.select_renderer方法
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/zuanzuan/p/10412165.html