Django-restframework 源碼分析之認證
前言
最近學習了 django 的一個 restframework 框架,對於裏面的執行流程產生了興趣,通過昨天一夜初步搞清楚了執行流程(部分方法還不太清楚),因而想詳細的總結一下當來一個請求時,在該框架裏面是如何執行的?python
啓動項目時
昨天在調試django時,發如今 APIView 中打的斷點沒有斷下來,而是打在 View 中的斷點斷下來了,調試了不少次,最後發現,在 django 項目啓動時,會首先加載 urls 中的文件,執行 views 中類的 as_view方法,實際上是繼承自 APIView 的,APIView 繼承自 django 原生 View 的as_view 方法。django
裏面一個參數叫 pattern_name,對應的值是admin:auth_group_change,以下圖所示:bootstrap
目前還不清楚這裏面的具體流程是什麼,可是並不妨礙閱讀以後的源碼,在這隻要清楚一點,在 Django 項目啓動時,路由所對應的CBV裏面的相關方法的內存地址已經獲取到。這樣作的好處就是提升效率,壞處可能有一點點,會提高性能的消耗。api
具體路由和邏輯代碼
在這裏假設來一個 GET 請求,urls 和 views裏面的代碼以下:框架
# urls.py url(r'^book/(?P<id>\d+)/', views.Book.as_view()),
# 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
方法,源碼以下:url
具體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方法
未完待續…...