Django 之 restframework 解析器源码分析

解析器分类:

  1. JSONPaser ----> 解析 JSON-serialized data (解析JSON序列化的数据)

  2.FormParser ---->解析form 表单中 urlencoded格式数据(application/x-ww-form-urlencoded)

  3.MartiPartParser---->解析 form 表单中 form-data 格式数据(Multipart/form-data)

  4.FileUploadParser---> 解析 '*/*',(Parser for file upload data.)

源码中的解析器

  • 展开源码你会发现,每个解析器下面都会定义一个 解析方法(这是一种面向对象的鸭子类型的体现)。

  • 前端传过的数据以及文件,在后端被使用的时候(request.data,request.FILES)时候解析器才执行解析。所以解析器执行的入口是 request.data or request.FILES

源码部分:

# Request-->_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:
            # 获取 请求body体中的内容
            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)
		# 如果没有解析器就报错
        if not parser:
            raise exceptions.UnsupportedMediaType(media_type)

        try:
            # parser 是已选择的解析器对象(有 JSONparser,Formparser,MultiPartParser,FileUploadParser 是种 ,每个对象里都有一个 parse 方法,用于解析数据或文件。(这里是一种面向对象的鸭子类型的体现))
            # 返回解析完的parsed对象
            parsed = parser.parse(stream, media_type, self.parser_context)
        except Exception:
            # If we get an exception during parsing, fill in empty data and
            # re-raise.  Ensures we don't simply repeat the error when
            # attempting to render the browsable renderer response, or when
            # logging the request or similar.
            self._data = QueryDict('', encoding=self._request._encoding)
            self._files = MultiValueDict()
            self._full_data = self._data
            raise

        # Parser classes may return the raw data, or a
        # DataAndFiles object.  Unpack the result as required.
        try:
            # 最终返回 parsed对象的数据和文件
            return (parsed.data, parsed.files)
        except AttributeError:
            empty_files = MultiValueDict()
            return (parsed, empty_files)

  

执行流程(以JSON 格式数据为例)

"""
-->1.request.data
-->2.执行request.data 中的 self._load_data_and_files()
-->3.执行self._load_data_and_files() 中的 self._data, self._files = self._parse()
-->4. 执行self._parse() 
    -->4.1.执行stream = self.stream-->self._load_stream() 获取请求内容
    -->4.2 执行parser = self.negotiator.select_parser(self, self.parsers)获取解析器
        -->4.2.1 执行 self.negotiator = negotiator or self._default_negotiator()
        --> 如果没有传 就去 配置文件中找api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS()
    -->4.3 执行 parsed = parser.parse(stream, media_type, self.parser_context) 返回通过不同解析器解析出来的被解析对象
    -->4.4 返回  
"""
View Code
原文地址:https://www.cnblogs.com/qianzhengkai/p/11144238.html