REST Framework組件的解析源碼
首先我們要知道解析器的作用
- 解析器就是對你請求體中的數據進行反序列化、封裝 把你的所有的請求數據都封裝在request.data中 以後就在request.data中獲取數據
我們先導入rest_framework的解析器
from rest_framework.parsers import JSONParser,FormParser
from rest_framework.parsers import JSONParser,FormParser
class PaserView(APIView):
parser_classes = [JSONParser,FormParser,]
#JSONParser:表示只能解析content-type:application/json的頭
#FormParser:表示只能解析content-type:application/x-www-form-urlencoded的頭
def post(self,request,*args,**kwargs):
#獲取解析後的結果
print(request.data)
return HttpResponse(‘paser‘)
在settings中的配置
#全局配置
REST_FRAMEWORK = {
#版本
"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
#解析器
"DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"]
}
先通過APIView進入源碼 因為APIView是rest_framework的源碼進入口
- 然後進入你的dispath函數中的initialize_request
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
return Request(
request, # 這個時候的request已是你原生的request然後傳遞進去
parsers=self.get_parsers(), #獲取你的多個解析器 get_parsers()是通過你的定義 parser_classes進行的得到的信息 然後得到的列表 賦值給parsers傳遞進去然後在內部處理
authenticators=self.get_authenticators(), # 獲取認證
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
然後你的self.get_parsers()獲取你的代碼中的parser內容賦值給parsers
def get_parsers(self):
"""
Instantiates and returns the list of parsers that this view can use.
"""
return [parser() for parser in self.parser_classes] # 返回列表生成式 遍歷你的self.parser_classes 是對你的在settings中設置的配置進行判斷
你的self.parser_classes是從你的requet類中的get_parsers是從最開始APIView中獲取值的 然後返回一個列表進行到request對象中
然後進入你的request對象中
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
‘The `request` argument must be an instance of ‘
‘`django.http.HttpRequest`, not `{}.{}`.‘
.format(request.__class__.__module__, request.__class__.__name__)
)
self._request = request # 對你的原生了request進行 封裝
self.parsers = parsers or () #如果有parsers請求體重的數據就拿到沒有就為空
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty
然後執行你的這個裏面的def _parse方法
def _parse(self): # 解析器會走這個
"""
Parse the request content, returning a two-tuple of (data, files) # 解析請求的內容會返回兩個一個元組內部有兩個參數
May raise an `UnsupportedMediaType`, or `ParseError` exception.
"""
media_type = self.content_type # 獲取你的請求體中的數據類型
try:
stream = self.stream
except RawPostDataException:
if not hasattr(self._request, ‘_post‘):
raise
# If request.POST has been accessed in middleware, and a method=‘POST‘
# request was made with ‘multipart/form-data‘, then the request stream
# will already have been exhausted.
if self._supports_form_parsing():
return (self._request.POST, self._request.FILES)
stream = None
if stream is None or media_type is None:
if media_type and is_form_media_type(media_type):
empty_data = QueryDict(‘‘, encoding=self._request._encoding)
else:
empty_data = {}
empty_files = MultiValueDict()
return (empty_data, empty_files)
parser = self.negotiator.select_parser(self, self.parsers) # select_parser 對你拿到的parsers實例化對象 然後select_parser再根據你的實例對象進行請求方式的匹配 self.parsers是拿到你的請求值
你的_parse是對你的init中的傳遞進來deparser進行加工判斷
_parse方法中的media_type = self.content_type # 獲取你的請求體中的數據類型 也是至關重要的,然後你的self.negotiator.select_parser() 就對你的傳遞進來的值進行解析判斷
點擊進入self.negotiator.select_parser()方法中
def select_parser(self, request, parsers):
"""
Given a list of parsers and a media type, return the appropriate
parser to handle the incoming request. 給定解析器列表和媒體類型,返回相應的
解析器來處理傳入的請求。
"""
for parser in parsers: # 對你傳遞進來的值進行請求方式的匹配
if media_type_matches(parser.media_type, request.content_type):
return parser
return None
negotiator.select_parser()是通過對象本身的media_type 請求方式對你的請求體中內容進行的解析 然後這一步才最終解析完畢
綜上就是rest_framework的源碼執行流程
-
首先你要先從APIView中獲取進入 在Request對象中中通過get_parsers方法獲取你的setting中設置的解釋器組件 然後循環這個解析器組件得到每一個解析器
-
然後得到的解析器給parsers通過第三path方法中的initialize_request方法內部的Request對象
-
然後Request中的_parse方法對你傳遞進來的然後針對你的parser解析器對象和請求方式media_type 獲取你的請求方式 進行請求方式和請求解析器的匹配
-
然後你的_parse中的select_parser方法根據 media_type和解析器對象進行匹配判斷 使用對應的解析器進行請求方式的解析
-
所以先是循環你的解析器對象 然後 把這個對象傳遞進Request中然後Request中的_parse中再對象你的請求方式和解析器匹配 然後選擇對應的解析器對你的 請求方式進行解析
純屬個人見解 看了兩天才看懂也是夠笨的了希望對正在鉆研的你有幫助、 與君共勉!!!
REST Framework組件的解析源碼