zoukankan      html  css  js  c++  java
  • REST Framework组件的解析源码

    首先我们要知道解析器的作用

    • 解析器就是对你请求体中的数据进行反序列化、封装 把你的所有的请求数据都封装在request.data中 以后就在request.data中获取数据

    我们先导入rest_framework的解析器

    from rest_framework.parsers import JSONParser,FormParser

    
    from rest_framework.parsers import JSONParser,FormParser
    
    class PaserView(APIView):
    
        parser_classes = [JSONParser,FormParser,]
        #JSONParser:表示只能解析content-type:application/json的头
        #FormParser:表示只能解析content-type:application/x-www-form-urlencoded的头
    
        def post(self,request,*args,**kwargs):
            #获取解析后的结果
            print(request.data)
            return HttpResponse('paser')

    在settings中的配置

    
    #全局配置
    REST_FRAMEWORK = {
        #版本
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",   
        #解析器
        "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"]
    }

    先通过APIView进入源码 因为APIView是rest_framework的源码进入口

    源码入口

    • 然后进入你的dispath函数中的initialize_request

    第二步

       def initialize_request(self, request, *args, **kwargs):
            """
            Returns the initial request object.
            """
            parser_context = self.get_parser_context(request)
    
            return Request(
                request,  # 这个时候的request已是你原生的request然后传递进去
                parsers=self.get_parsers(),  #获取你的多个解析器 get_parsers()是通过你的定义 parser_classes进行的得到的信息 然后得到的列表 赋值给parsers传递进去然后在内部处理
                authenticators=self.get_authenticators(), # 获取认证
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
    
    

    然后你的self.get_parsers()获取你的代码中的parser内容赋值给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]  # 返回列表生成式   遍历你的self.parser_classes 是对你的在settings中设置的配置进行判断
    

    你的self.parser_classes是从你的requet类中的get_parsers是从最开始APIView中获取值的 然后返回一个列表进行到request对象中

    这里写图片描述

    然后进入你的request对象中

    
     def __init__(self, request, parsers=None, authenticators=None,
                     negotiator=None, parser_context=None):
            assert isinstance(request, HttpRequest), (
                'The `request` argument must be an instance of '
                '`django.http.HttpRequest`, not `{}.{}`.'
                .format(request.__class__.__module__, request.__class__.__name__)
            )
    
            self._request = request     # 对你的原生了request进行 封装
            self.parsers = parsers or ()  #如果有parsers请求体重的数据就拿到没有就为空
            self.authenticators = authenticators or ()
            self.negotiator = negotiator or self._default_negotiator()
            self.parser_context = parser_context
            self._data = Empty
            self._files = Empty
            self._full_data = Empty
            self._content_type = Empty
            self._stream = Empty

    然后执行你的这个里面的def _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:
                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)  # select_parser 对你拿到的parsers实例化对象 然后select_parser再根据你的实例对象进行请求方式的匹配  self.parsers是拿到你的请求值
    
    

    你的_parse是对你的init中的传递进来deparser进行加工判断

    这里写图片描述

    _parse方法中的media_type = self.content_type # 获取你的请求体中的数据类型 也是至关重要的,然后你的self.negotiator.select_parser() 就对你的传递进来的值进行解析判断

    点击进入self.negotiator.select_parser()方法中

    这里写图片描述

       def select_parser(self, request, parsers):
            """
            Given a list of parsers and a media type, return the appropriate
            parser to handle the incoming request.   给定解析器列表和媒体类型,返回相应的
             解析器来处理传入的请求。
            """
            for parser in parsers:  # 对你传递进来的值进行请求方式的匹配
                if media_type_matches(parser.media_type, request.content_type):
                    return parser
            return None
    
    

    negotiator.select_parser()是通过对象本身的media_type 请求方式对你的请求体中内容进行的解析 然后这一步才最终解析完毕


    综上就是rest_framework的源码执行流程

    • 首先你要先从APIView中获取进入 在Request对象中中通过get_parsers方法获取你的setting中设置的解释器组件 然后循环这个解析器组件得到每一个解析器

    • 然后得到的解析器给parsers通过第三path方法中的initialize_request方法内部的Request对象

    • 然后Request中的_parse方法对你传递进来的然后针对你的parser解析器对象和请求方式media_type 获取你的请求方式 进行请求方式和请求解析器的匹配

    • 然后你的_parse中的select_parser方法根据 media_type和解析器对象进行匹配判断 使用对应的解析器进行请求方式的解析

    • 所以先是循环你的解析器对象 然后 把这个对象传递进Request中然后Request中的_parse中再对象你的请求方式和解析器匹配 然后选择对应的解析器对你的 请求方式进行解析

    纯属个人见解 看了两天才看懂也是够笨的了希望对正在钻研的你有帮助、 与君共勉!!!

  • 相关阅读:
    在主窗体中打开一个新子窗体,如果已有子窗体,则激活它,而不打开新的。
    文本的追加
    男人至少的品质底线
    做人,做事,生活,学习,爱情>人生
    日常中一些好用的小软件
    ◆2008 年广告创意设计师必备网址汇总◆
    在SharePoint中更改当前登录用户的密码
    SONY笔记本VGNSZ65装VISTA记
    Outlook收邮件速度超慢的原因
    Cisco路由器做限速
  • 原文地址:https://www.cnblogs.com/zhaoyunlong/p/9539671.html
Copyright © 2011-2022 走看看