首页 > 其他分享 >【DRF-08】rest-framework之解析器

【DRF-08】rest-framework之解析器

时间:2024-05-28 22:56:14浏览次数:18  
标签:解析器 type 08 parser request framework ._ data self

  • 1.解析器的作用

    • 根据请求头 content-type 选择对应的解析器对请求体内容进行处理。
    • 有application/json,x-www-form-urlencoded,form-data等格式, 可以自己自行配置支持或者不支持哪种格式, 一般在实际的生产环境中用json一种数据格式进行数据交互就够了, 如果需要form-data来进行文件处理,再将该格式加入到解析器中即可
  • 2.全局使用解析器

# setting.py
REST_FRAMEWORK = {
    "DEFAULT_VERSION":"v1",
    "ALLOWED_VERSIONS":["v1","v2"],
    "VERSION_PARAM":"version",

    "DEFAULT_PARSER_CLASSES":[
        "rest_framework.parsers.JSONParser",
        "rest_framework.parsers.FormParser",
        ]
}

# 视图
class ParserView(APIView):
    # parser_classes = [FileUploadParser]
    def post(self,request,*args,**kwargs):
        print(request.content_type)
        
        """
        1. 获取用户请求
        2. 获取用户请求体
        3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较
        4. JSONParser对象去请求体
        5. request.data
		"""
        
        print(request.data)
        return HttpResponse("解析器")
  • 3.不同解析器与传参的对应关系

  • 4.解析器源码流程

    • 4.1:首先还是走dispatch-->>initialize_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(), #  [Foo(),Bar()]
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )

def get_parsers(self):
    """
    Instantiates and returns the list of parsers that this view can use.
    """
    return [parser() for parser in self.parser_classes]

class APIView(View):
    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    。。。。
  • 4.2:当视图中调用request.data时,执行request中的data方法
@property
def data(self):
    if not _hasattr(self, '_full_data'):
        self._load_data_and_files()
    return self._full_data
  • 4.3:执行_load_data_and_files方法,调用self._parse()
def _load_data_and_files(self):
    """
    Parses the request content into `self.data`.
    """
    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

        # if a form media type, copy data & files refs to the underlying
        # http request so that closable objects are handled appropriately.
        if is_form_media_type(self.content_type):
            self._request._post = self.POST
            self._request._files = self.FILES
  • 4.4:执行self._parse,调用parser = self.negotiator.select_parser(self, self.parsers)
def _parse(self):
    """
    Parse the request content, returning a two-tuple of (data, files)

    May raise an `UnsupportedMediaType`, or `ParseError` exception.
    """
    # 用户提交的请求头的content_type的值
    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)
    # self.parsers(全局配置中的解析器)
    # self 请求对象self.content_type
    parser = self.negotiator.select_parser(self, self.parsers)

    if not parser:
        raise exceptions.UnsupportedMediaType(media_type)

    try:
        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:
        return (parsed.data, parsed.files)
    except AttributeError:
        empty_files = MultiValueDict()
        return (parsed, empty_files)

  • 4.5:执行select_parser,根据每个解析器的media_type与请求的content_type比较,返回对应的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
  • 4.6:执行4.4中parsed = parser.parse(stream, media_type, self.parser_context)方法。不同解析器的不同parser方法从而进行解析,如JSONParser
def parse(self, stream, media_type=None, parser_context=None):
    """
    Parses the incoming bytestream as JSON and returns the resulting data.
    """
    parser_context = parser_context or {}
    encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)

    try:
        decoded_stream = codecs.getreader(encoding)(stream)
        parse_constant = json.strict_constant if self.strict else None
        return json.load(decoded_stream, parse_constant=parse_constant)
    except ValueError as exc:
        raise ParseError('JSON parse error - %s' % str(exc))

标签:解析器,type,08,parser,request,framework,._,data,self
From: https://www.cnblogs.com/xwltest/p/18219140

相关文章

  • Android Media Framework(一)OpenMAX框架简介
    学习开源代码最快的方式是先阅读它的文档,再查看它的头文件,最后研读代码实现并进行编译调试。Android早期引入OpenMAXIL作为使用音视频编解码器的标准接口,了解AndroidMedia框架的底层运行原理要从OMXIL开始。在这一节,我们将阅读整理OpenMAXILSpec中的介绍和架构部分,以便对整......
  • Learning Model Predictive Control for Iterative Tasks. A Data-Driven Control Fra
    LearningModelPredictiveControlforIterativeTasks.AData-DrivenControlFramework一句话MPC:在每个采用点处,根据被控对象的状态和预测模型,预测系统在未来一段时间内的状态,依据某一性能指标(成本函数)来求解最优的一组控制序列,并将这组控制序列的第一个控制作用作为输出......
  • 【DRF-07】rest-framework之版本
    1.基于url的get传参方式(不推荐)1.1:通过自定义版本控制类,获取版本fromdjango.shortcutsimportrender,HttpResponsefromrest_framework.viewsimportAPIViewclassParamVersion(object):defdetermine_version(self,request,*args,**kwargs):version......
  • SQL Server2008 r2数据库备份还原与导入导出
    备份还原        在使用数据库时,数据丢失或损坏是一件非常糟糕的事,为了应对这类事情的发生,我们可以对数据库进行备份,数据丢失或损坏时,可以还原数据。数据的备份     1.创建备份设备    在“服务器对象”中找到“备份设备”,右键点击后选取“新......
  • CSP历年复赛题-P1058 [NOIP2008 普及组] 立体图
    原题链接:https://www.luogu.com.cn/problem/P1058题意解读:在m*n的平面上,输出若干个立方体,每一个格子可以有高度不同的多个立方体。解题思路:此题咋一看来,无从下手,仔细分析,其实一道模拟题。如何模拟?我们一起来解决一下几个关键问题:1、如何画图?要在平面上输出图案,本质上就是将......
  • 【舞台灯方案】LED驱动恒流芯片pwm深度调光APS54085降压IC
    产品描述APS54085是一款PWM工作模式,高效率、外围简单、内置功率MOS管,适用于5-100V输入的高精度降压LED恒流驱动芯片。最大电流2.0A。APS54085可实现线性调光和PWM调光,线性调光有效电压范围0.52-2.55V.PWM调光频率范围100HZ-30KHZ。APS54085工作频率可以通过R......
  • MySQL - [08] 存储过程
    题记部分  一、什么是存储过程  存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。  存储过程思想上很简单,就是数据库SQL语言层面的......
  • 命令启用Windows7 .NetFramework 3.5
    最近在测试某系统安装包在各个环境下的安装使用情况,在window7下使用时,安装完成iis后,发现.NetFramework3.5没有自动勾选;命令没有执行成功。通过以下命令可以在window7下打开自带的.netframework3.5.1(CMD窗口内执行)dism/online/enable-feature/featurename:NetFx3 ......
  • Android Media Framework - 开篇
    前言AndroidMedia是一块非常庞大的内容,上到APP的书写,中到播放器的实现、封装格式的了解,下到编解码组件的封装、VPUAPI的了解,每块内容的学习都需要我们下很大的功夫。此外,我们还要对相关的模块进行了解,比如AudioFlinger、SurfaceFlinger等,他们与Media相关交织共同构建了Android......
  • 【DRF-06】rest-framework之节流
    1.自定义节流类,基于用户IP限制访问频率1.1:自定义节流类importtimeVISIT_RECORD={}classVisitThrottle(BaseThrottle):'''#(1)取出访问者ip#(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走#(3)循......