基本代码结构

urls.py:

from django.conf.urls import url, include
from web.views.s5_parser import TestView urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]

views.py:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser class TestView(APIView):
# JSONParser:请求头content-type为application/json
# FormParser:请求头content-type为application/x-www-form-urlencoded
# MultiPartParser: 请求头content-type为multipart/form-data
# FileUploadParser:上传文件
parser_classes = [JSONParser, FormParser, MultiPartParser, 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('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

  parser_classes属性变量中的值,是各种解析器对象。前端会向后台发送不同类型的请求,而django后台的drf接口必须通过配置解析器才能获取到相关请求数据。常用的解析器主要是“JSONParser”和“FormParser”这两个解析器。

源码分析

  • 为什么会使用parser_classes属性变量,它有什么用?

  

  同样还是从APIView类的入口方法dispatch入口,在dispatch方法中,调用了initialize_request方法。这个方法在前文中已经说过,是用来封装django原生的request请求的。由上图知道,django原生的request请求数据被封装到了Request对象中,在实例化该对象时,将解析数据的解析器初始化到了parsers属性变量中。

  

  跳转到get_parsers方法中,可以看到,同样也是返回的是列表生成式。

  

  再跳转回APIView类中,可以看到属性变量parser_classes定义的地方。同样也可以通过settings配置文件进行全局配置。如果不需要进行全局配置,那就要在自定义的视图类中对parser_classes属性变量进行重新赋值,即:“parser_classes = [JSONParser, FormParser, MultiPartParser, FileUploadParser,]”。这列表元素都是解析器对象,只要这样配置好,drf就会根据parser_classes中的解析器去解析数据。

  • 为什么从request.data中获取数据?

  

  既然要分析为什么是从data中获取数据,那么分析的入口点当然就是data了。我们知道,django原生的request请求,会被drf通过Request对象封装,那么就跳转到Request类定义中看看这个“data”的实现。在data方法的实现中可以看到前端请求的数据是通过“_load_data_and_files”方法获取的,并且返回值是“_full_data”属性变量。先跳转到“_load_data_and_files”方法中:

  

  

  在“_load_data_and_files”方法中可知,是通过调用“_parse”方法去获取请求数据的,并且将请求数据保存在“_data”和“_files”属性变量中。除文件相关的数据外的数据都保存在了“_data”中,而“_data”中的数据又都赋值到“_full_data”属性变量中。又由上一张图可知,“data”方法的返回值是“_full_data”,即:data方法获取到的数据就是“_full_data”中的数据。

  再往下看,“content_type”属性变量是用来保存请求头的,所以,在基本代码结构中看到,只有设置了某些请求头才会通过“request.POST”来获取请求数据。

  下面跳转到“_parse”方法中:

  

  

  在“_parse”方法中,可以看到将获取到的请求头保存到了“media_type”变量中。然后又通过调用“select_parser(self, self.parsers)”方法,来选择所需要的解析器(参数“self.parsers”就是我们在自定义视图中“parser_classes”的值)。

  又通过,parser_classes中解析器对象中的parser方法来解析请求到的数据,即:“parsed = parser.parse(steam, media_type, self.parser_context)”。这里以“JSONParser”对象为例,由上图可知,media_type属性变量中保存的是该解析器所对应的请求头,self.parser_context中,保存的是从前端请求中获取到的请求头。

  再来到“JSONParser”类的“parse”方法中可知,再通过返回“json.load”来处理请求数据。返回的请求数据就会保存到“Request”类的“_parse”方法中的parsed变量中。而_parse方法的返回值为元组,第一个元素就是需要的数据。这些数据会在“_load_data_and_files”方法中,赋值给“Request”类的“_data”属性方法,而_data中的数据会赋值给“_full_data”中。因此,“Request”类中“data”方法返回值是“_full_data”,这样,就可以通过“request.data”获取请求数据。

全局配置

REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser'
'rest_framework.parsers.FormParser'
'rest_framework.parsers.MultiPartParser'
]
}

  配置加入不同的解析器,就会解析不同类型的请求数据,当然是可以同时配置加入多个解析器的。同样的,配置了全局解析器后,那么,在自定义的视图类中,就可以不用通过“parser_classes”属性变量进行添加解析器的。

Django 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的解析器与渲染器

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

  4. Django REST Framework - 分页 - 渲染器 - 解析器

    为什么要使用分页? 我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输过程中耗时也会 ...

  5. rest framework 之解析器

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

  6. Django REST Framework的序列化器是什么?

    # 转载请留言联系 用Django开发RESTful风格的API存在着很多重复的步骤.详细可见:https://www.cnblogs.com/chichung/p/9933861.html 过程往往 ...

  7. django rest framework 自定义验证器

    一.基于钩子函数: 官网上的例子: 官方提示:如果字段声明在序列化类上时,就具有参数required=Fasle的作用,当函数名中没有包括字段名时,那么这个验证函数就不起作用 二.基于类的验证器: 使 ...

  8. Django Rest framework 之 序列化

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

  9. Django Rest framework 之 版本

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

随机推荐

  1. 【python-appium】手机一直提示重新安装settings unlock 输入法等 注释掉以下代码

    注释掉目录:C:\Program Files (x86)\Appium\node_modules\appium\lib\devices\android\android.js this.initUnic ...

  2. Linux 查看IP

    UBuntu 系统下 按Ctrl+Alt+T 唤出终端 在终端输入: ifconfig 命令 点击回车 就可以看到自己电脑在局域网的IP地址了 图中第二行 inet 地址:192.168.1.101 ...

  3. Linux下Redis安装使用教程

    https://redis.io/download 第一步:安装redis需要在有c语言的编译环境下,执行命令安装c语言环境: yum install gcc-c++ https://blog.csd ...

  4. maya2012卸载/安装失败/如何彻底卸载清除干净maya2012注册表和文件的方法

    maya2012提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装maya2012失败提示maya2012安装未完成,某些产品无法安装,也有时候想重新安装maya ...

  5. 在jsp的js和css里面使用EL表达式取值|style里面用$取值

    众所周知,如果直接在jsp的js或者css语句块里面写${***}取值的话,程序会不识别这玩意,但是,我们有时候确实需要动态取值,比如,js为了获得对象的某一个值,不方便用js的getElementB ...

  6. 开源性能测试工具Locust使用篇(一)

    1. 环境准备 安装python3.6 ,安装步骤略 pip install locust 安装完成后使用locust -V检查 2.locust使用,先编辑一个简单的load_test.py的脚本 ...

  7. 第三篇: 服务消费者(Feign)

    本文根据https://blog.csdn.net/forezp/article/details/81040965写出,修正了部分瑕疵,在此对那位博主表示感谢. 上一篇文章讲述通过RestTempla ...

  8. D3.js的一些基础部分 (v3版本)

    最近公司有需求要做一些可视化的功能.之前一直都是用Echarts做的,但是Echarts难以满足我们的需求,经过多方请教,查找发现D3可以满足我们的需求.第一次接触到D3,发现这些图标的可交互性非常丰 ...

  9. Datatable数据转换成excel导出时 数值类型在EXCEL中为文本形式 无法进行统计

    功能背景 有地税上以及各企业的一个缴费情况的比对,基于两表进行匹配查看数据是否在合理范围内,对比对完成表进行数值导出. 2.问题描述 匹配和生成匹配结果导出已成功完成,但是在数值列导出后变成了文本形式 ...

  10. android开发学习——day8

    关于UI学习的总结 EditText的练习 MainActivity.java代码 package test.example.com.ch02_button; import android.suppo ...