DRF-解析器组件源码解析
Posted benson321
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DRF-解析器组件源码解析相关的知识,希望对你有一定的参考价值。
解析器组件源码解析
解析器组件源码解析 1 执行request.data 开始找重装的request中的data方法 2 在dispatch找到重装的request def dispatch(self, request, *args, **kwargs): request = self.initialize_request(request, *args, **kwargs) ***这里开始找data 3 在initialize_request中找到实例request的类Request() 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 ) 得到类对象Request(),注意parsers=self.get_parsers()后面会回来找 4 Request()中找到data方法 5 在data方法中--关注返回值 @property def data(self): if not _hasattr(self, ‘_full_data‘): self._load_data_and_files() return self._full_data 由于返回值默认:self._full_data = Empty 所以self._load_data_and_files()应该对_full_data进行复制了 6 从_load_data_and_files()找到_full_data def _load_data_and_files(self): if not _hasattr(self, ‘_data‘): self._data, self._files = self._parse() if self._files: self._full_data = self._data.copy() self._full_data.update(self._files) else: self._full_data = self._data 这里我们把self._parse()的结果分别复制给了self._data, self._files,且都放在了_full_data中,接下来观察self._parse()都给了什么值 7 _parse() def _parse(): parser = self.negotiator.select_parser(self, self.parsers) parsed = parser.parse(stream, media_type, self.parser_context) empty_files = MultiValueDict() return (parsed, empty_files) parsed通过parser获取,而传入的参数中的self.parsers,就是我们初始化Request()中传入的参数parsers=self.get_parsers() // *****这里开始开始和parser_classes我们的设置解析数据类型设置相关了 8 我们回到步骤3找到parsers=self.get_parsers() 9 在get_parsers()中 return [parser() for parser in self.parser_classes] 得到从self.parser_classes中循环的列表 // *****选择从调用的视图类中获取parser_classes,没有从APIView中获取parser_classes 10 在APIView中获取到parser_classes parser_classes = api_settings.DEFAULT_PARSER_CLASSES 11 从api_settings查找DEFAULT_PARSER_CLASSES方法或属性 api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) @property def user_settings(self): if not hasattr(self, ‘_user_settings‘): self._user_settings = getattr(settings, ‘REST_FRAMEWORK‘, {}) return self._user_settings class APISettings(): def __init__(defaults=None): self.defaults = defaults or DEFAULTS # 这里将DEFAULTS字典放在实例对象中, def __getattr__(self, attr): if attr not in self.defaults: raise AttributeError("Invalid API setting: ‘%s‘" % attr) try: # Check if present in user settings val = self.user_settings[attr] except KeyError: # Fall back to defaults val = self.defaults[attr] # Coerce import strings into classes if attr in self.import_strings: val = perform_import(val, attr) # Cache the result self._cached_attrs.add(attr) setattr(self, attr, val) return val self.defaults = defaults or DEFAULTS --》这里将DEFAULTS字典放在实例对象中,我们发现DEFAULT_PARSER_CLASSES 就在字典中 由于没有DEFAULT_PARSER_CLASSES方法,我们执行__getattr__方法 1***** val = self.user_settings[attr]优先从配置中找有没有配置的路由解析方法,如果没配置 2***** val = self.defaults[attr]从实例化对象的内存空间中找方法 3 val = perform_import(val, attr)将‘rest_framework.parsers.JSONParser‘转化成JSONParser
解析器顺序
当前访问视图类下------------》全局settings---------》默认default
使用
# 设置全局解析方式 REST_FRAMEWORK={ ‘DEFAULT_PARSER_CLASSES‘: ( ‘rest_framework.parsers.JSONParser‘, ‘rest_framework.parsers.FormParser‘, ‘rest_framework.parsers.MultiPartParser‘ ), }
# 当前访问视图类下设置解析方式 from rest_framework.parsers import JSONParser from rest_framework.views import APIView class LoginView(APIView): parser_classes = [JSONParser] def get(self,request): print(‘get‘) return render(request,‘login.html‘) def post(self,request): print(‘body‘,request.body) print(request.data) print(‘data‘,request.data) # print(‘POST‘, request.POST) return HttpResponse(‘OK‘)
# 默认使用的解析方式 class APIView(View): parser_classes = api_settings.DEFAULT_PARSER_CLASSES
以上是关于DRF-解析器组件源码解析的主要内容,如果未能解决你的问题,请参考以下文章