前戏
解析器是干什么的? 因为前后端分离, 因为可能采用 JSON,xml,html 等各种不同格式的内容, 后端必须要有一个解析器来解析前端发送过来的数据, 也就是翻译器! 否则后端凭什么看懂前端的数据? 对应地, 后端也有一个渲染器 Render, 和解析器是相反的方向, 将后端的数据翻译成前端能明白的数据格式.
DRF 框架提供了许多内置的 Parser 类, 用来处理各种媒体类型的请求, 比如 JSON, 比如 xml. 还支持自定义解析器, 可以灵活地设计 API 接受的媒体类型.
Django 原生的解析器对于 post 的数据, 如果要从 request.body 中解析出来放到 request.POST 中, 那么必须同时满足两个条件:
请求头部 Content_type = 'application/x-www-form-urlencoded'
数据格式必须是: name=xxx&password=xxx&email=xxx.....
而对于前端发送过来的例如 JSON 格式的数据则无法处理 (当然你自己处理也是可以的).DRF 则不同, 它提供了一些额外的解析器帮我们处理各种格式.
DRF 的 parsers 模块非常简单, 只定义了几个解析器类:
BaseParser: 解析器基类, 以下四个类都直接继承它
- JSONParser
- FormParser
- MultiPartParser
- FileUploadParser
- 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
- FileUploadParser
解析原始文件上传内容. 此时, request.data 属性将是一个字典, 并且只包含一个键, 这个键叫做'file' , 对应的值包含上传的文件内容.
如果使用 FileUploadParser 解析器的视图, 在被调用的时候 URL 中携带一个 filename 关键字参数, 则该参数将被用作文件名. 如果在没有这个关键字参数的情况下调用它, 则客户端必须在 HTTP 头部的 Content-Disposition 中设置文件名.
DRF 在运行的时候如何知道该使用哪个解析器呢?
DRF 将有效的解析器集定义为类的列表. 当 request.data 被访问时, REST 框架将检查请求头部的 Content-Type 属性, 以此来确定要使用哪个解析器来解析数据. 所以, 要注意! 解析器只有在请求 request.data 的时候才会被调用! 如果不需要 data 数据, 那么就不用解析.
注意: 在开发客户端应用程序时, 务必确保在请求头部中包含 Content-Type 属性. 如果未设置内容类型, 则大多数客户端将默认使用'application/x-www-form-urlencoded' 类型
解析器的相关配置参数
可以在 Django 项目的 settings.py 文件中, 使用 DEFAULT_PARSER_CLASSES 配置项, 进行全局的解析器设置. 例如, 以下设置仅允许解析 JSON 格式的请求, 而不是默认的 JSON 或表单数据:
- REST_FRAMEWORK = {
- 'DEFAULT_PARSER_CLASSES': (
- 'rest_framework.parsers.JSONParser',
- )
- }
当然, 也可以同时支持多种解析器, 比如下面的配置, 这也是 DRF 默认的解析器配置:
- REST_FRAMEWORK = {
- 'DEFAULT_PARSER_CLASSES': (
- 'rest_framework.parsers.JSONParser',
- 'rest_framework.parsers.FormParser',
- 'rest_framework.parsers.MultiPartParser',
- )
- }
几种解析器的写法没有先后顺序的要求, 不像中间件那样的配置有顺序关系.
DRF 支持视图级别的解析器, 比如为基于 APIView 的类视图专门指定使用的解析器, 核心是指定 parser_classes 属性为某个解析器:
- from rest_framework.parsers import JSONParser
- from rest_framework.response import Response
- from rest_framework.views import APIView
- class ExampleView(APIView):
- # 配置解析器
- parser_classes = (JSONParser,)
- def post(self, request):
- return Response("Hello World")
当然, 也可以为使用 @api_view 装饰器改造的视图指定专用的解析器, 核心是 @parser_classes((JSONParser,)) 装饰器:
- from rest_framework.decorators import api_view
- from rest_framework.decorators import parser_classes
- from rest_framework.parsers import JSONParser
- from rest_framework.response import Response
- @api_view(['POST'])
- @parser_classes((JSONParser,)) # 配置解析器
- def example_view(request):
- return Response({'received data': request.data})
如果全局配置了解析器, 视图里也配置了, 则视图里的解析器具有更高的优先级.
自定义解析器
要自定义解析器, 必须继承 BaseParser 类, 设置 .media_type 属性, 并实现 .parse(self, stream, media_type, parser_context) 方法, 该方法应返回将用于填充 request.data 属性的数据.
parse() 方法的参数说明:
stream: 类似于流的对象, 表示请求的主体.
media_type: 请求内容的媒体类型, 可选. 根据请求头部的 Content-Type: , 这可能比渲染器的 media_type 属性更具体, 并且可能包括媒体类型参数. 例如 "text/plain; charset=utf-8" .
parser_context: 可选, 字典格式. 如果提供, 将包含解析请求内容可能需要的任何其他上下文. 可选, 字典格式. 如果提供, 将包含解析请求内容可能需要的任何其他上下文.
下面自定义了一个纯文本解析器, 它将字符串形式表示的请求内容, 填充到 request.data 属性.
- from rest_framework.parsers import BaseParser
- class PlainTextParser(BaseParser):
- """
- 纯文本解析器
- """ media_type ='text/plain'
- def parse(self, stream, media_type=None, parser_context=None):
- """简单的返回一个请求主体内容的字符串形式"""
- return stream.read()
YAML 解析器
djangorestframework-YAML 包为我们提供了解析和渲染 YAML 格式的能力. 它以前直接包含在 REST 框架包中, 现在作为第三方包出现.
直接用 pip 安装
pip install djangorestframework-YAML
可以进行下面的配置:
- REST_FRAMEWORK = {
- 'DEFAULT_PARSER_CLASSES': (
- 'rest_framework_yaml.parsers.YAMLParser',
- ),
- 'DEFAULT_RENDERER_CLASSES': (
- 'rest_framework_yaml.renderers.YAMLRenderer',
- ),
- }
xml 解析器
pip install djangorestframework-xml
配置
- REST_FRAMEWORK = {
- 'DEFAULT_PARSER_CLASSES': (
- 'rest_framework_xml.parsers.XMLParser',
- ),
- 'DEFAULT_RENDERER_CLASSES': (
- 'rest_framework_xml.renderers.XMLRenderer',
- ),
- }
来源: http://www.bubuko.com/infodetail-3685894.html