rest-framework之解析器

rest-framwork之解析器

解析器(一般不需要动,项目最开始全局配置一下就可以了)

作用:控制视图类能够解析的前端传过来的数据格式

'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser', # media_type = 'application/json'
        'rest_framework.parsers.FormParser', # media_type = 'application/x-www-form-urlencoded'
        'rest_framework.parsers.MultiPartParser' # media_type = 'multipart/form-data'
    ),

全局使用

在setting中配置:

REST_FRAMEWORK = {
				"DEFAULT_PARSER_CLASSES":[
                    # 仅处理请求头content-type为application/json的请求体
					'rest_framework.parsers.JSONParser',
				]
			}

在局部使用

在视图类中:

parser_classes=[JSONParser,]

源码流程:

当调用request.data的时候去执行解析方法,根据传过来的编码方式选择一个解析器对象,调用解析器对象的parser方法完成解析

1 在调用request.data时,才进行解析,由此入手
    @property
    def data(self):
        if not _hasattr(self, '_full_data'):
            self._load_data_and_files()
        return self._full_data
        
2 查看self._load_data_and_files()方法---->self._data, self._files = self._parse()

        def _parse(self):
            #用户请求头里content_type的值
            media_type = self.content_type

            #self.parsers 就是用户配置的parser_classes = [FileUploadParser,FormParser ]
            #self里就有content_type,传入此函数
            parser = self.negotiator.select_parser(self, self.parsers)

3 查看self.negotiator.select_parser(self, self.parsers)
     def select_parser(self, request, parsers):
        #同过media_type和request.content_type比较,来返回解析器,然后调用解析器的解析方法
        #每个解析器都有media_type = 'multipart/form-data'属性
        for parser in parsers:
            if media_type_matches(parser.media_type, request.content_type):
                return parser
        return None
    
4 最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)
1 Request实例化,parsers=self.get_parsers()
    Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
2 get_parsers方法,循环实例化出self.parser_classes中类对象
    def get_parsers(self):
        return [parser() for parser in self.parser_classes]            

3 self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
4 api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,找不到,会到getattr方法
        def __getattr__(self, attr):
            if attr not in self.defaults:
                raise AttributeError("Invalid API setting: '%s'" % attr)

            try:
                #调用self.user_settings方法,返回一个字典,字典再取attr属性
                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
 5 user_settings方法 ,通过反射去setting配置文件里找REST_FRAMEWORK属性,找不到,返回空字典
    @property
    def user_settings(self):
        if not hasattr(self, '_user_settings'):
            self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
        return self._user_settings
posted @ 2019-07-05 17:02  Lip&Hip  阅读(171)  评论(0编辑  收藏  举报