DRF--解析器Parsers

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: DRF--解析器Parsers

前戏


解析器是干什么的?因为前后端分离,因为可能采用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',
    ),
}

相关文章
|
数据库 Python
django drf 实现只有超级用户才能注册账号(涉及自定义权限permissions,获取token信息解析token信息)
django drf 实现只有超级用户才能注册账号(涉及自定义权限permissions,获取token信息解析token信息)
|
索引 数据格式 XML
Solr所有的查询解析器Query Parsers(转:http://blog.csdn.net/jiangchao858/article/details/53859731)
摘要: Solr除了支持常见的解析器之外,还有一些特殊用途的解析器,为了便于之后查阅,总结一下。本文整理自Solr官方文档。 解析器 说明 Standard Query Parser Solr的标准查询解析器Standard Query Parser DisMax Query Parser Solr的查询解析器DisMax Query Parser Extended DisM
1648 0
|
19天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
39 0
|
19天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
29 0
|
19天前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
33 0
|
19天前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
45 0
|
17天前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
39 5
|
18天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
18天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
19天前
|
存储 Java API
从源码角度解析ArrayList.subList的几个坑!
从源码角度解析ArrayList.subList的几个坑!

推荐镜像

更多