一、示例

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/json
  • FormParser,解析数据类型:content-type:application/x-www-form-urlencoded
  • 支持全局配置解析器类型

rest framework 之解析器的更多相关文章

  1. Django Rest framework 之 解析器

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  2. DRF Django REST framework 之 解析器(二)

    引入 Django Rest framework帮助我们实现了处理application/json协议请求的数据,如果不使用DRF,直接从 request.body 里面拿到原始的客户端请求的字节数据 ...

  3. Django Rest Framework之解析器

    基本代码结构 urls.py: from django.conf.urls import url, include from web.views.s5_parser import TestView u ...

  4. Django REST framework的解析器与渲染器

    解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentTy ...

  5. django的rest framework框架——版本、解析器、序列化

    一.rest framework的版本使用 1.版本可以写在URL中,通过GET传参,如 http://127.0.0.1:8082/api/users/?version=v1 (1)自定义类获取版本 ...

  6. Django高级篇三。restful的解析器,认证组件,权限组件

    一.rest=framework之解析器 1)解析器作用. 根据提交的数据.只解析某些特定的数据.非法数据不接收,为了系统安全问题 比如解析的数据格式有 有application/json,x-www ...

  7. Django rest framework(5)----解析器

    目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...

  8. Restful framework【第五篇】解析器

    基本使用 -解析器 -源码从request.data -全局配置 -'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser'], -局 ...

  9. python-django rest framework框架之解析器

    1.解析器 : 对请求的数据进行解析 - 请求体进行解析. 解析器在你不拿请求体数据时 不会调用. class UsersView(APIView): def get(self,request,*ar ...

随机推荐

  1. ZROI 暑期高端峰会 A班 Day5 计算几何

    内积(点积) 很普及组,不讲了. \[(a,b)^2\le(a,a)(b,b)\] 外积(叉积) 也很普及组,不讲了. 旋转 对于矩阵 \(\begin{bmatrix}\cos\theta\\\si ...

  2. 软件工程卷1 抽象与建模 (Dines Bjorner 著)

    I 开篇 1. 绪论 II 离散数学 2. 数 (已看) 3. 集合 4. 笛卡尔 5. 类型 6. 函数 7. λ演算 8. 代数 9. 数理逻辑 III 简单RSL 10. RSL中的原子类型和值 ...

  3. JS- 数组去重方法整理

    [indexOf] 简单而且可以加中文,但是兼容性不好,indexOF兼容到ie9 function uniq(arr) { var temp = []; for (let i = 0; i < ...

  4. wkhtmltopdf cpdf HTML转pdf 及pdf合并

    将 html 转为 pdf :wkhtmltopdf wkhtmltopdf 是一个使用 webkit 网页渲染引擎开发的用来将 html 转成 pdf 的工具,可以跟多种脚本语言进行集成来转换文档. ...

  5. 关于qt creator各种假死的问题

    来自CSDN网友( qq191329827)内容,亲自尝试,且经历一致: 我有两个笔记本,1个台式机,都装了qt, 然后,我的thinkpad x1c,装上之后creator各种假死,网上看了好多解决 ...

  6. Java集合详解4:一文读懂HashMap和HashTable的区别以及常见面试题

    <Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...

  7. ReentrantReadWriteLock源码分析

    代码在后面 读锁 = 共享锁 读锁写锁,公用一个Sync AQS state. 写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁,别人也不会进来获取锁. 写锁的获取跟ReentarntLock一 ...

  8. javascript 函数的暂停和恢复

    javascript 异步编程从来都是一个难题,最开始我们用 callback,但随之触发了回调地狱,于是"发明" Promise 解决 callback 嵌套过深的问题.然而由于 ...

  9. FRP represents an intersection of two programming paradigms.

    FRP represents an intersection of two programming paradigms. Functional programming Functional progr ...

  10. .net core将URL请求格式化为XML或JSON(网站动态生成sitemap.xml)

    .net core将URL请求格式化为XML或JSON(网站动态生成sitemap.xml) 首先设置 Startup.cs 文件 配置 ConfigureServices services .Add ...