ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

解析器的作用

2022-01-19 20:33:51  阅读:221  来源: 互联网

标签:解析器 self parser request rest framework import 作用


rest-framework之解析器

一 解析器的作用

根据请求头 content-type 选择对应的解析器对请求体内容进行处理。

有application/json,x-www-form-urlencoded,form-data等格式

二 全局使用解析器

setting里

复制代码

REST_FRAMEWORK = {
  'DEFAULT_PARSER_CLASSES':[
      'rest_framework.parsers.JSONParser'
      'rest_framework.parsers.FormParser'
      'rest_framework.parsers.MultiPartParser'
  ]

}

复制代码

路由:

urlpatterns = [
  url(r'test/', TestView.as_view()),
]

视图函数:

复制代码

from rest_framework.views import APIView
from rest_framework.response import Response

class TestView(APIView):
  def post(self, request, *args, **kwargs):
      print(request.content_type)

      # 获取请求的值,并使用对应的JSONParser进行处理
      print(request.data)
      # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
      print(request.POST)
      print(request.FILES)
      return Response('POST请求,响应内容')

  def put(self, request, *args, **kwargs):
      return Response('PUT请求,响应内容')

复制代码

 

 

三 局部使用解析器

a. 仅处理请求头content-type为application/json的请求体

复制代码

from django.conf.urls import url, include
from web.views.s5_parser import TestView

urlpatterns = [
  url(r'test/', TestView.as_view(), name='test'),
]

复制代码

复制代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser


class TestView(APIView):
  parser_classes = [JSONParser, ]

  def post(self, request, *args, **kwargs):
      print(request.content_type)

      # 获取请求的值,并使用对应的JSONParser进行处理
      print(request.data)

      # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
      print(request.POST)
      print(request.FILES)

      return Response('POST请求,响应内容')

  def put(self, request, *args, **kwargs):
      return Response('PUT请求,响应内容')

复制代码

b. 仅处理请求头content-type为application/x-www-form-urlencoded 的请求体

复制代码

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
  url(r'test/', TestView.as_view(), name='test'),
]

复制代码

复制代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FormParser


class TestView(APIView):
  parser_classes = [FormParser, ]

  def post(self, request, *args, **kwargs):
      print(request.content_type)

      # 获取请求的值,并使用对应的JSONParser进行处理
      print(request.data)

      # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
      print(request.POST)
      print(request.FILES)

      return Response('POST请求,响应内容')

  def put(self, request, *args, **kwargs):
      return Response('PUT请求,响应内容')

复制代码

c. 仅处理请求头content-type为multipart/form-data的请求体

复制代码

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
  url(r'test/', TestView.as_view(), name='test'),
]

复制代码

复制代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import MultiPartParser


class TestView(APIView):
  parser_classes = [MultiPartParser, ]

  def post(self, request, *args, **kwargs):
      print(request.content_type)

      # 获取请求的值,并使用对应的JSONParser进行处理
      print(request.data)
      # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
      print(request.POST)
      print(request.FILES)
      return Response('POST请求,响应内容')

  def put(self, request, *args, **kwargs):
      return Response('PUT请求,响应内容')

复制代码

复制代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
  <input type="text" name="user" />
  <input type="file" name="img">

  <input type="submit" value="提交">

</form>
</body>
</html>

复制代码

d. 仅上传文件

复制代码

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
  url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
]

复制代码

复制代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser


class TestView(APIView):
  parser_classes = [FileUploadParser, ]

  def post(self, request, filename, *args, **kwargs):
      print(filename)
      print(request.content_type)

      # 获取请求的值,并使用对应的JSONParser进行处理
      print(request.data)
      # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
      print(request.POST)
      print(request.FILES)
      return Response('POST请求,响应内容')

  def put(self, request, *args, **kwargs):
      return Response('PUT请求,响应内容')

复制代码

复制代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
  <input type="text" name="user" />
  <input type="file" name="img">

  <input type="submit" value="提交">

</form>
</body>
</html>

复制代码

e. 同时多个Parser

当同时使用多个parser时,rest framework会根据请求头content-type自动进行比对,并使用对应parser

 

复制代码

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
  url(r'test/', TestView.as_view(), name='test'),
]

复制代码

复制代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser


class TestView(APIView):
  parser_classes = [JSONParser, FormParser, MultiPartParser, ]

  def post(self, request, *args, **kwargs):
      print(request.content_type)

      # 获取请求的值,并使用对应的JSONParser进行处理
      print(request.data)
      # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
      print(request.POST)
      print(request.FILES)
      return Response('POST请求,响应内容')

  def put(self, request, *args, **kwargs):
      return Response('PUT请求,响应内容')

复制代码

 

四 源码分析

复制代码

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

复制代码

 

0

0

标签:解析器,self,parser,request,rest,framework,import,作用
来源: https://www.cnblogs.com/thaimj1314520/p/15823976.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有