一、解析器的作用

根据请求头content-type选择对应的解析器对请求体内容进行处理。

有application/json,x-www-form-urlencoded,form-data等格式

二、局部使用解析器

a、仅处理请求头content-type为application/json的请求体

路由:

    url(r'^publish/$',views.PublishView.as_view()),

视图:

# 局部使用解析器
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser
class PublishView(APIView):
parser_classes = [JSONParser,]
# 获取所有的数据
def get(self,request):
publish_list=models.Publish.objects.all()
ps=PublishSerializers(publish_list,many=True)
return Response(ps.data)
def post(self,request,*args,**kwargs):
print(request.content_type)
# 获取请求的值,并使用对应的jsonparser进行处理
print(request.data)
print(type(request.data)) #application/x-www-form-urlencoded或multipart/form-data时,request.POST才有值
print(request.POST)
print(request.FILES)
return Response('post请求,响应内容')
def put(self,request,*args,**kwargs):
return Response('put请求,响应内容')

通过get方法可以获取数据,对数据新增的时候只有json这一种格式,使用其它方式新增数据提示失败,不支持

b,仅处理请求头content-type为application/x-www-form-urlencodede的请求体

设置url:

    url(r'^publish/$',views.TestView.as_view()),

设置路由:


from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FormParser
class TestView(APIView):
parser_classes = [FormParser,]
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请求,响应内容')
def put(self,request,*args,**kwargs):
return Response('put请求,响应内容')

c,仅处理请求头content-type为multipart/form-data的请求体

设置url:

    url(r'^publish/$',views.TestView.as_view()),

设置视图:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FormParser
from rest_framework.parsers import MultiPartParser
# 只处理请求头content-type为multipart/from-data的请求体
class TestView(APIView):
parser_classes = [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请求,响应内容')
def put(self,request,*args,**kwargs):
return Response('put请求,响应内容')

只允许form-data格式的请求,其它格式或请求全部会拒绝:

新建一个前端页面提交新增数据输入框:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/publish/" method="post" enctype="multipart/form-data">
<input type="text" name="user" />
<input type="text" name="city"> <input type="submit" value="提交"> </form>
</body>
</html>

提交数据后返回页面:

d,仅上传文件:

路由:

    url(r'publish/(?P<filename>[^/]+)', views.TestView.as_view()),

视图:

# 只处理文件
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser class TestView(APIView):
parser_classes = [FileUploadParser, ] def post(self, request, filename, *args, **kwargs):
print(filename)
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请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

编辑前端web页面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/publish/f1.numbers" method="post" enctype="multipart/form-data">
<input type="text" name="user" />
<input type="file" name="img"> <input type="submit" value="提交"> </form>
</body>
</html>

前端页面展示:

文件上传成功,获取返回值:

e,同时多个Parser

同时使用多个parser时,rest framework会根据请求头content-type自动进行对比,并使用对应parser

设置路由:

    url(r'publish/', views.TestView.as_view()),

视图:

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请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

支持:

JSONParser, FormParser, MultiPartParser提交数据

三、全局使用解析器
在settings中设置:
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser'
'rest_framework.parsers.FormParser'
'rest_framework.parsers.MultiPartParser'
] }

路由设置:

urlpatterns = [
url(r'test/', TestView.as_view()),
]

视图函数:

from rest_framework.views import APIView
from rest_framework.response import Response class TestView(APIView):
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请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

四、源码分析

1 在调用request.data时,才进行解析,由此入手
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data 2 查看self._load_data_and_files()方法---->self._data, self._files = self._parse() def _parse(self):
#用户请求头里content_type的值
media_type = self.content_type #self.parsers 就是用户配置的parser_classes = [FileUploadParser,FormParser ]
#self里就有content_type,传入此函数
parser = self.negotiator.select_parser(self, self.parsers) 3 查看self.negotiator.select_parser(self, self.parsers)
def select_parser(self, request, parsers):
#同过media_type和request.content_type比较,来返回解析器,然后调用解析器的解析方法
#每个解析器都有media_type = 'multipart/form-data'属性
for parser in parsers:
if media_type_matches(parser.media_type, request.content_type):
return parser
return None 4 最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)
1 Request实例化,parsers=self.get_parsers()
Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
2 get_parsers方法,循环实例化出self.parser_classes中类对象
def get_parsers(self):
return [parser() for parser in self.parser_classes] 3 self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
4 api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,找不到,会到getattr方法
def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr) try:
#调用self.user_settings方法,返回一个字典,字典再取attr属性
val = self.user_settings[attr]
except KeyError:
# Fall back to defaults
val = self.defaults[attr] # Coerce import strings into classes
if attr in self.import_strings:
val = perform_import(val, attr) # Cache the result
self._cached_attrs.add(attr)
setattr(self, attr, val)
return val
5 user_settings方法 ,通过反射去setting配置文件里找REST_FRAMEWORK属性,找不到,返回空字典
@property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings

rest_framework:解析器的更多相关文章

  1. rest_framework解析器组件源码流程

    rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...

  2. rest_framework(解析器 上)

    rest_framework 解析器 对请求题数据进行解析 url from django.conf.urls import url,include from cmdb import views ur ...

  3. rest_framework 解析器(下 全局配置使用)

    解析器 一般都是全局设置 参考文档 www.cnblogs.com/wupeiqi/articles/.html REST_FRAMEWORK=( "DEFAULT_PARSER_CLASS ...

  4. rest_framework之解析器详解 05

    解析器就是服务端写api,对于前端用户发来的数据进行解析.解析完之后拿到自己能用数据. 本质就是对请求体中的数据进行解析. django的解析器 post请求过来之后,django 的request. ...

  5. 「Django」rest_framework学习系列-解析器

    满足两个要求,request.Post中才有值 1.请求头要求:请求头中的Content-Type为application/x-www-form-urlencoded 2.数据格式要求 name=x& ...

  6. Django Rest Framework源码剖析(五)-----解析器

    一.简介 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数据格式,比如xml,所以需要解析这类数 ...

  7. rest framework 之解析器

    一.示例 1.api/urls.py from django.urls import path, re_path from api.views import UserView, ParserView ...

  8. rest_framework之解析器、路由控制、分页

    解析器 我们都知道,网络传输数据只能传输字符串格式的,如果是列表.字典等数据类型,需要转换之后才能使用 但是我们之前的rest_framework例子都没有转换就直接可以使用了,这是因为rest_fr ...

  9. 六、django rest_framework源码之解析器剖析

    1 绪论 网络传输数据只能传输字符串格式的,如果是列表.字典等数据类型,需要转换之后才能使用但是我们之前的rest_framework例子都没有转换就直接可以使用了,这是因为rest_framewor ...

随机推荐

  1. css的三种导入方式

    内联样式表 <p style="font-size:50px; color:blue">css内联样式表</p> 内部样式表 <style type= ...

  2. Nginx架构分析(20200202)

    Nginx模块化 Nginx基于模块化设计,每个模块是一个功能实现,分布式开发,团队协作 核心模块.标准HTTP模块.可选HTTP模块.邮件模块.第三方模块 编译后的源码目录objs/ngx_modu ...

  3. go 环境及4开发

    国内加速 在gopath目录执行 go env -w GOPROXY=direct go env -w GOSUMDB=off go env -w GOPROXY=https://goproxy.io ...

  4. 使用Sqlserver 2012 导出表数据为SQL脚本

    目录 前言 具体步骤 前言 很多时候,我们需要把数控库中的表的数据导出成SQL脚本的情形.然后,在别的库执行的情况. 以下,总结使用Sqlserver 2012数据库中表数据导出成SQL脚本的步骤. ...

  5. 【redis】spring boot利用redis的Keyspace Notifications实现消息通知

    前言 需求:当redis中的某个key失效的时候,把失效时的value写入数据库. github: https://github.com/vergilyn/RedisSamples 1.修改redis ...

  6. MySQL8.0远程连接和用户授权相关设置

    文章目录 1.开启MySQL远程连接 2.关闭MySQL远程连接 3.修改防火墙规则,开放端口 4.创建用户以及给用户授权 5.删除用户及权限 1.开启MySQL远程连接 mysql -u root ...

  7. 【论文翻译】An overiview of gradient descent optimization algorithms

    这篇论文最早是一篇2016年1月16日发表在Sebastian Ruder的博客.本文主要工作是对这篇论文与李宏毅课程相关的核心部分进行翻译. 论文全文翻译: An overview of gradi ...

  8. object解构赋值

    let options = { title: 'menu', width: 100, height: 200 } //如果简写,变量名必须和属性名一致 let {title,width,height} ...

  9. 白面系列 docker

    在讲docker之前,首先区分2个概念,容器和虚拟机. 容器: 虚拟机: 简单来说,容器虚拟化操作系统:虚拟机虚拟化硬件. 容器粒度更小更灵活:虚拟机包含资源更多更大. docker就是用来做容器化的 ...

  10. C#简单的LogHelper

    适用于不想使用log4net等第三方的Log工具的LogHelper.正规的还是要使用<C# 工具类LogHelper>的这种做法. using System; using System. ...