rest framework 之解析器
一、示例
1、api/urls.py
from django.urls import path, re_path
from api.views import UserView, ParserView
urlpatterns = [
# path('users/', UserView.as_view()),
re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(), name='api_user'),
path('parser/', ParserView.as_view(), name='api_parer'), # 添加这句
]
2、api/views.py
JSONParser:只能解析content-type:application/json的头FormParser:只能解析content-type:application/x-www-form-urlencoded的头
from rest_framework.parsers import JSONParser, FormParser
class ParserView(APIView):
parser_classes = [JSONParser, FormParser]
def post(self, request, *args, **kwargs):
print(request.data)
return HttpResponse('解析')
3、使用 postman 发送 json 数据测试后台是否能解析:
(1)、设置为 post 方式,headers 中添加数据类型为 json

(2)、body 中选择 raw,然后选择 json 类型,最后就是在空白处构建要发送的 json 数据(记得是双引号):

后台结果:

如果是 content-type:application/x-www-form-urlencoded 类型数据,不需要设置请求头,默认就是。但是 body 中需要设置为 x-www-form-urlencoded 。
二、源码分析
1、dispatch()
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
# 对原生的 request 对象进行加工,丰富了
# request= Request(request,parsers=self.get_parsers(),authenticators=self.get_authenticators(),negotiator=self.get_content_negotiator(),parser_context=parser_context)
# 第一个参数为原生的 request 对象,封装原生 request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
2、initialize_request()
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object. 封装原生 request 对象
"""
parser_context = self.get_parser_context(request)
return Request(
request,
# 获取所有解析器
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
3、get_parsers()
def get_parsers(self):
"""
Instantiates and returns the list of parsers that this view can use.
返回次视图可以使用的解析器列表
"""
return [parser() for parser in self.parser_classes]
4、parser_classes
class APIView(View):
# The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
# 从 settings 中获取解析器
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
# Allow dependency injection of other settings to make testing easier.
settings = api_settings
5、全局配置解析器 settings:
REST_FRAMEWORK = {
# 解析器
"DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"]
}
源码流程图

根据请求头 content-type 选择对应的解析器就请求体内容进行处理。
三、仅处理请求头 content-type 为 application/json 的请求体
1、urls.py
from django.urls import path, re_path, include
from api.views import TestView2
urlpatterns = [
re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]
2、views.py
rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser
from rest_framework.response import Response
class TestView2(APIView):
parser_classes = [JSONParser]
def post(self, request, *args, **kwargs):
print(request.content_type) # application/json
# 获取请求值,并发 JSONParser 处理
print(request.data) # {'name': 'rose', 'age': 18}
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST) # <QueryDict: {}>
print(request.FILES) # <MultiValueDict: {}>
return Response('响应内容')

四、仅处理请求头 content-type 为 application/x-www-form-urlencoded 的请求体
1、urls.py
from django.urls import path, re_path, include
from api.views import TestView2
urlpatterns = [
re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]
2、views.py
rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser
from rest_framework.response import Response
class TestView2(APIView):
parser_classes = [FormParser]
def post(self, request, *args, **kwargs):
print(request.content_type) # application/x-www-form-urlencoded
# 获取请求值,并发 JSONParser 处理
print(request.data) # <QueryDict: {'123': ['']}>
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST) # <QueryDict: {'123': ['']}>
print(request.FILES) # <MultiValueDict: {}>
return Response('响应内容')
五、仅处理请求头content-type为multipart/form-data的请求体
1、urls.py
from django.urls import path, re_path, include
from api.views import TestView2
urlpatterns = [
re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]
2、views.py
rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
from rest_framework.response import Response
class TestView2(APIView):
parser_classes = [MultiPartParser]
def post(self, request, *args, **kwargs):
print(request.content_type) # multipart/form-data
# 获取请求值,并发 JSONParser 处理
print(request.data)
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('响应内容')
3、upload.html
<!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>
六、仅上传文件
1、urls.py
from django.urls import path, re_path, include
from api.views import TestView2
urlpatterns = [
re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]
2、views.py
rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser, FileUploadParser
from rest_framework.response import Response
class TestView2(APIView):
parser_classes = [FileUploadParser]
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('响应内容')
3、upload.html
<!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>
七、其他
多个 parser
当同时使用多个 parser 时,rest framework 会根据请求头 content-type 自动进行比对,并使用对应 parser
#!/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请求,响应内容')
全局使用
settings.py
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser'
'rest_framework.parsers.FormParser'
'rest_framework.parsers.MultiPartParser'
]
}
Tips: 个别特殊的值可以通过Django的request对象 request._request 来进行获取
总结
JSONParser,解析数据类型:content-type:application/jsonFormParser,解析数据类型:content-type:application/x-www-form-urlencoded- 支持全局配置解析器类型
rest framework 之解析器的更多相关文章
- Django Rest framework 之 解析器
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- DRF Django REST framework 之 解析器(二)
引入 Django Rest framework帮助我们实现了处理application/json协议请求的数据,如果不使用DRF,直接从 request.body 里面拿到原始的客户端请求的字节数据 ...
- Django Rest Framework之解析器
基本代码结构 urls.py: from django.conf.urls import url, include from web.views.s5_parser import TestView u ...
- Django REST framework的解析器与渲染器
解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentTy ...
- django的rest framework框架——版本、解析器、序列化
一.rest framework的版本使用 1.版本可以写在URL中,通过GET传参,如 http://127.0.0.1:8082/api/users/?version=v1 (1)自定义类获取版本 ...
- Django高级篇三。restful的解析器,认证组件,权限组件
一.rest=framework之解析器 1)解析器作用. 根据提交的数据.只解析某些特定的数据.非法数据不接收,为了系统安全问题 比如解析的数据格式有 有application/json,x-www ...
- Django rest framework(5)----解析器
目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...
- Restful framework【第五篇】解析器
基本使用 -解析器 -源码从request.data -全局配置 -'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser'], -局 ...
- python-django rest framework框架之解析器
1.解析器 : 对请求的数据进行解析 - 请求体进行解析. 解析器在你不拿请求体数据时 不会调用. class UsersView(APIView): def get(self,request,*ar ...
随机推荐
- Spring Boot 知识笔记(创建maven项目、HTTP接口)
一.使用Maven手工创建SpringBoot应用(IDEA) 1. 点击File——New——Project——Maven——Next,填写相关信息,创建项目. 2. 在pom.xml中添加相关 ...
- 华为鸿蒙OS发布!方舟支持混合编译,终将可替换安卓?
前言 有关于鸿蒙的消息之前也有说过,就在昨天下午,华为举行了2019开发大会,正式推出了鸿蒙os系统(Harmony).其相关负责人表示,也是基于微软内核的全场景分布式OS 鸿蒙凭借微内核的优势, ...
- nexus没有授权导致的错误
错误详情信息: 错误信息: [ERROR] Failed to execute goal on project blog: Could not resolve dependencies for pro ...
- mac系统中怎么打开rar/zip等压缩文件?
平常使用mac的同学们,可能经常要接受下别人发过来的rar文件,可惜的时mac os x系统默认是不能打开rar文件(不知道以后苹果会支持rar不?),那么我们该如何去解圧rar文件,接下来我将介绍. ...
- pytest学习笔记二 fixtrue
前言 官方文档关于fixture功能的解释如下: The purpose of test fixtures is to provide a fixed baseline upon which test ...
- Python的WEB框架
Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Python的标准库外,其不依赖任何其他模块. ? 1 2 ...
- 左倾红黑树——左倾2-3树(不是jdk1.8的TreeMap的红黑树)
public class RBTree<K extends Comparable<K>, V> { public static boolean RED = true; publ ...
- URL中出现了%E2%80%8E(Zero-Width Space)
下面两个url地址,看起来是一样的,但是粘贴到记事本里会发现一个多出了很长的空格 url: '/secure/Dishes/GetList', url: '/secure/Dishes/GetLis ...
- IIS 10 PHP 运行环境
1.下载php for windows 解压到指定目录 https://windows.php.net/download/ 2.安装iis 勾选CGI 3 ,处理映射 4.添加测试站点测试是否已经 ...
- Scala Types 1
在 Scala 中所有值都有一种对应的类型 单例类型 形式:value.type,返回类型 value / null 场景1:链式API调用时的类型指定 class Super { def m1(t: ...