一、示例

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. ubuntu容器化开发系统配置 相关下载地址(laravel)

    ubuntu64位 18.04(开发使用桌面版本) Nginx PHP7.3 开发工具:PHPStorm 其他技术栈:laravel.VUE.NodeJs https://laravel.com/ h ...

  2. nRF51822 看门狗和OTA (无线升级功能)的尴尬笔记

    很久没有记笔记了.今天要记点东西,不然以后又忘记了. 随着时代的发展,现在的SDK已经是13.0了.蓝牙5.0也就来了.废话就少说了,记笔记吧. 两年前搞过nRF51822 的无线升级功能,那时候用的 ...

  3. JavaScriptDOM编程学习笔记(二)图片库案例

    <JavascriptDOM编程艺术>提供一个图片库的demo,主要讲解如何更好的使用JavaScript在网页中,跟随作者的思路来分析一下这个案例 首先需求是将图片发布到网上,但是如果发 ...

  4. 关于“100g文件全是数组,取最大的100个数”解决方法汇总

    原题如下: 有一个100G大小的文件里存的全是数字,并且每个数字见用逗号隔开.现在在这一大堆数字中找出100个最大的数出来. 我认为,首先要摸清考官的意图.是想问你os方面的知识,还是算法,或者数据结 ...

  5. Win10 系统直接在目录下打开cmd

    每次用cmd命令,就要定位到当前文件夹,很麻烦 这里介绍一种直接定位到要操作的文件夹的方法: 操作步骤: (1)选择要cmd的文件夹,按住Shift键,鼠标右键快捷方式,先打开Powershell窗口 ...

  6. SpringBoot扩展点之二:ApplicationRunner和CommandLineRunner的扩展

    CommandLineRunner并不是Spring框架原有的概念,它属于SpringBoot应用特定的回调扩展接口: public interface CommandLineRunner { /** ...

  7. Delphi 开发微信公众平台 (二)- 用户管理

    一.用户标签管理 开发者可以使用用户标签管理的相关接口,实现对公众号的标签进行创建.查询.修改.删除等操作,也可以对用户进行打标签.取消标签等操作. 1.创建标签 /// <summary> ...

  8. Github Markdown 图片如何并排显示

    Github Markdown 图片如何并排显示   要一张图片接着一张图片的写,中间不能有换行.如果换行的话则图片也换行 正确的写法: ![描述](图片链接)![描述](图片链接)![描述](图片链 ...

  9. SpringBoot引入第三方jar包或本地jar包的处理方式

    在开发过程中有时会用到maven仓库里没有的jar包或者本地的jar包,这时没办法通过pom直接引入,那么该怎么解决呢 一般有两种方法 第一种是将本地jar包安装在本地maven库 第二种是将本地ja ...

  10. Windows 查看端口占用进程并关闭

    当我们在运行一些软件需要特定软件(如tomcat)时,有可能会碰上端口被占用的情况,这时候我们可能就需要更改端口或把占用端口的进程结束掉,因为更换端口可能会导致当前环境产生一些的问题或是需要重新配置其 ...