1褐鸥,
request.data
將傳來(lái)的json數(shù)據(jù)解析成了字典的形式,我們可以使用request.data.get('')
來(lái)獲取相應(yīng)的值赐稽。我們知道原生django是不支持解析json
數(shù)據(jù)的叫榕,所以是DRF給解析了浑侥。為什么能解析json
類(lèi)型呢?除了json
類(lèi)型晰绎,別的類(lèi)型還支持不支持寓落?能不能自己限制只能解析json數(shù)據(jù)呢?這就需要繼續(xù)研究了荞下。從request入手伶选。-
2,查看
APIView中的dispatch
發(fā)現(xiàn)尖昏,用initialize_request
方法進(jìn)行變身仰税,實(shí)例化了一個(gè)新的request對(duì)象并賦值給request- ①,這個(gè)方法前面一部分將request對(duì)象傳進(jìn)了
initialize_request
方法進(jìn)行二次封裝,形成了一個(gè)【新的request對(duì)象】
def dispatch(self, request, *args, **kwargs): request = self.initialize_request(request, *args, **kwargs) self.request = request
- ②抽诉,實(shí)例化了一個(gè)Request類(lèi)的一個(gè)對(duì)象陨簇,返了回去【注意實(shí)例化過(guò)程中穿的參數(shù):parsers(解析器的意思)】
def initialize_request(self, request, *args, **kwargs): parser_context = self.get_parser_context(request)【↓返回實(shí)例化對(duì)象】 return Request(request,parsers=self.get_parsers(),authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(),parser_context=parser_context)
- ③,這個(gè)類(lèi)在實(shí)例化的時(shí)候
class Request(object): def __init__(self, request, parsers=None, authenticators=None,negotiator=None, parser_context=None): self._request = request 【由此可見(jiàn)迹淌,新的request._request就是原來(lái)的request對(duì)象河绽,但是我們一般不用,因?yàn)楹罄m(xù)還做了處理】 self.parsers = parsers or () @property def query_params(self): return self._request.GET 【使用這個(gè)方法就可以得到源類(lèi)的request對(duì)象的GET數(shù)據(jù)】
- ①,這個(gè)方法前面一部分將request對(duì)象傳進(jìn)了
-
3唉窃,在新的request類(lèi)中找到了
request.data
這個(gè)方法葵姥,這才是真正解析的開(kāi)始。-
①句携,Request類(lèi)中的data方法榔幸,屬性方法
@property def data(self): if not _hasattr(self, '_full_data'): self._load_data_and_files() return self._full_data
-
②,_load_data_and_files中矮嫉,有一個(gè)
self._parse
方法def _load_data_and_files(self): if not _hasattr(self, '_data'): self._data, self._files = self._parse()
-
③削咆,找到這個(gè)
_parse
方法def _parse(self): media_type = self.content_type 【拿到請(qǐng)求頭中的數(shù)據(jù)類(lèi)型】根據(jù)請(qǐng)求頭中的數(shù)據(jù)類(lèi)型,對(duì)應(yīng)不同的解析器進(jìn)行解析 parser = self.negotiator.select_parser(self, self.parsers)【self.parsers蠢笋,選擇解析器的步驟】 try: parsed = parser.parse(stream, media_type, self.parser_context)【解析的過(guò)程拨齐,不做仔細(xì)介紹】
-
④,選擇解析器的過(guò)程中有一個(gè)
self.parsers
昨寞,這就回到了實(shí)例化的時(shí)候瞻惋,返回查看Request類(lèi)的init中:self.parsers = parsers or () 實(shí)例化request對(duì)象時(shí):parsers=self.get_parsers()【此時(shí)的self是舊的,指的是自定義類(lèi)的self某個(gè)對(duì)象】
-
⑤援岩,自定義視圖類(lèi)的方法中歼狼,用了一個(gè)列表生成式,形成一個(gè)解析器對(duì)象的列表
def get_parsers(self): return [parser() for parser in self.parser_classes] 返回步驟③享怀,查看select_parser羽峰,for循環(huán)解析器 def select_parser(self, request, parsers): for parser in parsers: if media_type_matches(parser.media_type, request.content_type): return parser
-
⑥,返回到了最初的自定義視圖類(lèi)的
perser_classes
中如果自己設(shè)置了就用自己的,自己沒(méi)設(shè)置就用父類(lèi)的梅屉。 1值纱,自己設(shè)置的情況可以理解。 2坯汤,自己沒(méi)設(shè)置虐唠,用父類(lèi)的情況(APIView): parser_classes = api_settings.DEFAULT_PARSER_CLASSES 【api_settings】點(diǎn)了一下屬性,但是沒(méi)有此屬性 api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) 【APISettings實(shí)例化的對(duì)象】 【DEFAULTS是配置文件里面的一個(gè)個(gè)鍵值對(duì)】 所以走了__getattr__方法 def __getattr__(self, attr): try: val = self.user_settings[attr] 【執(zhí)行了此函數(shù)惰聂,得出的應(yīng)該是一個(gè)字典疆偿,且拿到了執(zhí)行后的attr的對(duì)應(yīng)值】 except KeyError: val = self.defaults[attr] 【全局找不到,就走默認(rèn)】 @property def user_settings(self): if not hasattr(self, '_user_settings'): self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})【此setting是原生django的】 return self._user_settings settings = LazySettings()【一個(gè)LazySettings對(duì)象】 from django.conf import settings 這個(gè)是django的全局配置
-
-
4庶近,步驟⑥的具體解析:
1翁脆,parser_classes = api_settings.DEFAULT_PARSER_CLASSES 2眷蚓,api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) 3鼻种,class APISettings(object): def __init__(self, user_settings=None, defaults=None, import_strings=None): if user_settings: self._user_settings = self.__check_user_settings(user_settings) self.defaults = defaults or DEFAULTS self.import_strings = import_strings or IMPORT_STRINGS self._cached_attrs = set() 4,api_settings.DEFAULT_PARSER_CLASSES 點(diǎn)不到沙热,就會(huì)找__getattr__方法 5叉钥,def __getattr__(self, attr):【attr就是找不到的這個(gè)DEFAULT_PARSER_CLASSES】 try: 【如果報(bào)錯(cuò),就走下面】 val = self.user_settings[attr] 【⑥⑦⑧解析】 except KeyError: val = self.defaults[attr] --》【默認(rèn)配置】 return val 6篙贸,@property def user_settings(self): if not hasattr(self, '_user_settings'): 【沒(méi)有這個(gè)屬性投队,走下面↓】 self._user_settings = getattr(settings, 'REST_FRAMEWORK', {}) return self._user_settings 7,self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})【settings是兩個(gè)settings加起來(lái)一起】 全局的源碼級(jí)別的改不了爵川,所以只能從自己的項(xiàng)目里的settings中改敷鸦。 如果自己配置了,就返回自己配置的那個(gè)寝贡,沒(méi)配置就返回空字典扒披。 8,配置了REST_FRAMEWORK圃泡,但是取不到值就報(bào)錯(cuò)碟案。 空字典[attr]也報(bào)錯(cuò),只要報(bào)錯(cuò)就走下面颇蜡。 也就是說(shuō)想要走這個(gè)价说,必須配置REST_FRAMEWORK并且里面有對(duì)應(yīng)的鍵。
最后得到查找順序:
1风秤,先找自己視圖類(lèi)里面的鳖目。
2,找不到自己的找全局(django的本項(xiàng)目中的setting)缤弦。
3疑苔,再找就是默認(rèn)(rest_framework這個(gè)包中的setting)。