Django restframework 源碼分析之認證詳解
前言
最近學(xué)習了 django 的一個 restframework 框架,對于里面的執(zhí)行流程產(chǎn)生了興趣,經(jīng)過昨天一晚上初步搞清楚了執(zhí)行流程(部分方法還不太清楚),于是想詳細的總結(jié)一下當來一個請求時,在該框架里面是如何執(zhí)行的?
啟動項目時
昨天在調(diào)試django時,發(fā)現(xiàn)在 APIView 中打的斷點沒有斷下來,而是打在 View 中的斷點斷下來了,調(diào)試了很多次,最后發(fā)現(xiàn),在 django 項目啟動時,會首先加載 urls 中的文件,執(zhí)行 views 中類的 as_view方法,其實是繼承自 APIView 的,APIView 繼承自 django 原生 View 的as_view 方法。
里面一個參數(shù)叫 pattern_name,對應(yīng)的值是admin:auth_group_change,如下圖所示:

目前還不清楚這里面的具體流程是什么,但是并不妨礙閱讀之后的源碼,在這只要清楚一點,在 Django 項目啟動時,路由所對應(yīng)的CBV里面的相關(guān)方法的內(nèi)存地址已經(jīng)獲取到。這樣做的好處就是提高效率,壞處可能有一點點,會提升性能的消耗。
具體路由和邏輯代碼
在這里假設(shè)來一個 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 中一個是路由分發(fā)方法,一個是獲取單本圖書信息(通過 id)。
as_view 具體執(zhí)行流程
在項目啟動時,相應(yīng)的函數(shù)內(nèi)存地址已經(jīng)獲取到,那么具體是怎么獲取到的呢?
在上面的代碼中可以看到 Book 類是繼承自 APIView 類的,所以在路由配置里面執(zhí)行的 as_view 方法如果 Book 類沒有重寫,那么執(zhí)行的就是按照 mro 列表順序查找到的第一個方法,在這里執(zhí)行的是 APIView 類中的 as_view 方法。
查看該源碼如下:

APIView 類的父類是 View 類,查看該類的 as_view 方法,源碼如下:

具體 as_view 就是將 view 函數(shù)的內(nèi)存地址返回,以便請求來時直接調(diào)用。
而 initkwargs 這個參數(shù)應(yīng)該是由 django 內(nèi)部傳的一些參數(shù),如下所示:

請求到來時
因為經(jīng)過 django 先執(zhí)行了 as_view 返回 view 的內(nèi)存地址,所以會直接執(zhí)行 view 函數(shù),如下:

在這里該 self 由于是 繼承自 APIView 類的 Book 類的對象,所以 dispatch 方法首先去自身找,之后去父類找,在 APIView 類中找到 dispatch 方法,源碼如下:

initialize_request方法:
源碼如下:

在實例化 Request 對象時, authenticators 參數(shù)需要在認證時使用,所以先把這個參數(shù)的值找出來。步驟如下:
調(diào)用 self.get_authenticators

找到 self.authentication_classes

找到 api_settings,才能找到DEFAULT_AUTHENTICATION_CLASSES

DEFAULT和IMPORT_STRINGS參數(shù)
DEFAULT參數(shù)

IMPORT_STRINGS參數(shù)

實例化 APISettings 對象

通過__getattr__方法獲取值

執(zhí)行perform_import方法

執(zhí)行import_from_string

執(zhí)行import_module

執(zhí)行_bootstrap._gcd_import

執(zhí)行_sanity_check

_sanity_check返回,執(zhí)行_find_and_load方法

所以通過__getattr__的到的是一個列表,里面是兩個類,分別是[rest_framework_authentication_SessionAuthentication, rest_framework_authentication_BasicAuthentication]
到這里,initialize_request方法執(zhí)行結(jié)束,得到一個經(jīng)過 Request 類實例化的 request 對象,該對象里面含有原生 request 對象,可以通過 request._request 取到。
initial 方法:
源碼如下:

這里傳入的 request 參數(shù)是經(jīng)過 Request 封裝后的參數(shù)
執(zhí)行g(shù)et_format_suffix

執(zhí)行完這個方法, self_format_kwarg = None ,
執(zhí)行perform_content_negotiation

執(zhí)行self.get_renders

執(zhí)行self.get_content_negotiator

執(zhí)行 conneg.select_renderer方法

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python利用內(nèi)置庫實現(xiàn)數(shù)據(jù)的加密與校驗
這篇文章主要為大家詳細介紹了如何使用Python內(nèi)置庫實現(xiàn)數(shù)據(jù)的加密和校驗,為開發(fā)者提供全方位的數(shù)據(jù)安全解決方案,感興趣的小伙伴可以跟隨小編一起學(xué)習一下2023-12-12
Python編寫可視化界面的全過程(Python+PyCharm+PyQt)
這篇文章主要給大家介紹了關(guān)于Python編寫可視化界面的相關(guān)資料,主要使用了Python+PyCharm+PyQt,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2021-05-05
Python基于sftp及rsa密匙實現(xiàn)遠程拷貝文件的方法
這篇文章主要介紹了Python基于sftp及rsa密匙實現(xiàn)遠程拷貝文件的方法,結(jié)合實例形式分析了基于RSA秘鑰遠程登陸及文件操作的相關(guān)技巧,需要的朋友可以參考下2016-09-09
Python請求庫發(fā)送HTTP POST請求的示例代碼
這段代碼使用了Python的requests庫來發(fā)送HTTP POST請求,向本地服務(wù)器的API發(fā)送數(shù)據(jù),并處理響應(yīng),一步步解釋這個代碼2024-08-08
Python包中__init__.py文件的作用與用法實例詳解
我們新建python包時常常會看到一個__init _.py文件,下面這篇文章主要給大家介紹了關(guān)于Python包中__init__.py文件的作用與用法的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-06-06

