Django(49)drf解析模組源碼分析
前言
上一篇分析了請求模組的源碼,如下:
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
上述源碼中parsers=self.get_parsers()
就是解析模組源碼的入口
源碼分析
我們點擊get_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]
該方法實例化並返回此視圖可以使用的解析器列表,我們點擊parser_classes
,查看解析器列表
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
我們會發現解析器列表,是從api_settings
中的DEFAULT_PARSER_CLASSES
查找的,而api_settings
又等於APISettings
中的DEFAULTS
,我們可以從settings
中的DEFAUITS
列表的DEFAULT_PARSER_CLASSES
,如下:
DEFAULTS = {
# Base API policies
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
],
}
我們可以看到,drf默認的解析器列表中有3個解析器,這3個解析器中都有media_type
屬性,代表支援解析的數據提交類型
- JSONParser:
media_type = 'application/json'
- FormParser:
media_type = 'application/x-www-form-urlencoded'
- MultiPartParser:
media_type = 'multipart/form-data'
如果我們想在以上3個解析器的基礎上,再加上文件類型的解析器,那麼需要全局配置。
全局配置
我們可以在settings.py
文件中設置REST_FRAMEWORK
配置,具體設置如下:
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
'rest_framework.parsers.FileUploadParser'
],
}
這樣,我們以後所有繼承於APIView
的類視圖都可以解析上面配置的4種數據類型,但是如果我們想某個視圖只能解析json
格式的數據,那麼就需要局部配置
局部配置
默認全局配置是因為我們寫的視圖繼承自APIView
,APIView
中配置了類屬性parser_classes
,所以我們自己編寫的視圖函數中,也設置個類屬性,並且導入JSONParser
解析器
from rest_framework.parsers import JSONParser
class TestView(APIView):
# 局部解析類配置
parser_classes = [JSONParser]
def post(self, request, *args, **kwargs):
print(request.data)
return Response("drf post ok")
接著我們使用application/x-www-form-urlencoded
提交數據,會有如下報錯
{
"detail": "不支援請求中的媒體類型 「application/x-www-form-urlencoded」。"
}
然後我們使用multipart/form-data
提交數據,也會報錯
{
"detail": "不支援請求中的媒體類型 「multipart/form-data; boundary=--------------------------022567055086460827891894」。"
}
最後我們使用application/json
提交數據,響應成功
"drf post ok"
自定義解析器
如果我們想自定義一個解析器,也很簡單,默認的3個解析器都繼承自BaseParser
,我們查看下源碼
class BaseParser:
"""
All parsers should extend `BaseParser`, specifying a `media_type`
attribute, and overriding the `.parse()` method.
"""
media_type = None
def parse(self, stream, media_type=None, parser_context=None):
"""
Given a stream to read from, return the parsed representation.
Should return parsed data, or a `DataAndFiles` object consisting of the
parsed data and files.
"""
raise NotImplementedError(".parse() must be overridden.")
如果我們需要自定義解析器,那麼就必須繼承自BaseParser
,並且設置屬性media_type
,還要重寫parse
方法,有需求的小夥伴可以自行嘗試,這裡就不演示了