首页 > 其他分享 >28.解析器Parser

28.解析器Parser

时间:2022-09-19 17:58:43浏览次数:59  
标签:解析器 Parser media parser 28 data parse type

什么是解析器

  • 因为前后端分离,可能有json、xml、html等各种不同格式的内容
  • 后端也必须要有一个解析器来解析前端发送过来的数据
  • 不然后端无法处理前端数据
  • 后端有一个渲染器Render,和解析器是相反方向,将后端数据翻译成前端能明白的数据格式
    Django原生的解析器
  • Django原生的解析器对于post的数据,如果要从request.body中解析出来放到request.POST中
  • 必须满足两个条件
  REST框架的解析器
  • REST框架提供了很多内置的Parser类,用来处理各种媒体类型的请求,比如json、xml,还支持自定义解析器
  • BaseParser:解析器基类,以下四个类都直接继承他
  • JSONParser
  • FormParser
  • MultiPartParser
  • FileUploadParser
  解析器源码解析
"""
BaseParser解析器基类源码
相当于是留了一个坑,被继承后重写
定义了空的 midia_type 媒体类型
定义了parse方法以及对应参数 
"""
class BaseParser:
    media_type = None
    def parse(self, stream, media_type=None, parser_context=None):
        # 没有实现实现这个方法的异常,没有写任何代码
        raise NotImplementedError(".parse() must be overridden.")
'''
JSONParser解析器源码
继承BaseParser
'''

class JSONParser(BaseParser):
    media_type = 'application/json'  # 定义媒体类型
    renderer_class = renderers.JSONRenderer #渲染器,解析是解析json那么返回也应该渲染json返回
    strict = api_settings.STRICT_JSON # 限制设置

    def parse(self, stream, media_type=None, parser_context=None):
        # 如果有解析上下文,将parser_context赋值parser_context,否则赋值一个空字典
        parser_context = parser_context or {}
        # 上下文如果有编码方式,赋值给encoding,否则使用默认的编码格式
        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))
            
            
'''
其他解析器大同小异 
'''
  解析器触发及相关参数配置
  • DRF将有效的解析器集定义为类的列表。当 request.data 被访问时,REST框架将检查请求头的 Content-Type 属性
  • 以此来确定要使用哪个解析器来解析数据。
  • 解析器只有在请求request.data的时候才会被调用!如果不需要data数据,那么就不用解析
  • 在Django项目的settings.py文件中 DEFAULT_PARSER_CLASSES 进行全局的解析器设置

# 默认的解析器配置
# 几种解析器的写法没有先后顺序的要求,不像中间件那样的配置有顺序关系
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':(
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
)
}

'''
如果我们配置第三方解析器 ,例如yml等
解析器和渲染器都需要配置,一般是配对使用的
配置格式:app.file.calss
'''
  视图级别解析器 单独指定的优先级高于全局的解析器配置,单独指定什么,就只能用什么解析器  
# 类属性指定
class ExampleView(APIView):
   # 通过parser_classes指定该视图的解析器,值是一个元组
    parser_classes = (JSONParser,)
    def post(self, request, format=None):
        return Response({'received data': request.data})
 
#函数装饰器指定
from rest_framework.decorators import parser_classes 
@api_view(['POST'])
@parser_classes((JSONParser,))
def testApi(request):
    ...
    自定义解析器
要自定义解析器,必须继承 BaseParser 类
设置 .media_type 属性
实现parse(self, stream, media_type, parser_context) 方法
该方法应返回将用于填充 request.data 属性的数据
 
#示例-文本解析器
class TextParser(BaseParser):
media_type = 'text/plain' #媒体类型
def parse(self, stream, media_type=None, parser_context=None):
    return stream.read() #返回读取的内容
解析器区别
解析器区别 JSONParser
解析 JSON 格式的请求内容
其.media_type属性值为 application/json
FormParser
解析HTML表单内容,使用QueryDict的数据填充request.data
这也是Django原生支持的解析方式。
通常同时支持FormParser和MultiPartParser两种解析器,以便完全支持HTML表单数据。
.media_type: application/x-www-form-urlencoded
MultiPartParser
解析多部分的HTML表单内容,支持文件上传
.media_type: multipart/form-data

HTML的form表单的enctype属性规定了form表单在发送数据到服务器时的编码方式
有
三种方式:
application/x-www-form-urlencoded
    默认的编码方式,常用于键值对数据
    但是在用文本的传输和MP3等大型文件的时候,使用这种编码效率低下
    
multipart/form-data
    指定传输数据为二进制类型,比如图片、mp3、文件
    
text/plain
    纯文体的传输。空格转换为 “+” 加号,但不对特殊字符编码。使用较少
FileUploadParser
解析原始文件上传内容。此时, request.data 属性将是一个字典,并且只包含一个键'file' ,对应的值包含上传的文件内容。
如果使用FileUploadParser解析器的视图,在被调用的时候URL中携带一个 filename 关键字参数
则该参数将被用作文件名。如果在没有这个关键字参数的情况下调用它,则客户端必须在
HTTP头部的 Content-Disposition 中设置文件名。例如 Content-Disposition:attachment; filename=upload.jpg 
.media_type: */*
FileUploadParser 用于原生的文件上传请求。对于在浏览器中上传或者使用带有分段上传功能的客户端使用MultiPartParser 解析器
由于 FileUploadParser 的 media_type 属性值是 */* ,表示可以接受所有内容类型,所以无需指定别的解析器,指定 FileUploadParser 就足够了。
 

标签:解析器,Parser,media,parser,28,data,parse,type
From: https://www.cnblogs.com/Mickey-7/p/16708502.html

相关文章