DRF-解析器组件源码解析
解析器组件源码解析
解析器组件源码解析
1 执行request.data 开始找重装的request中的data方法
2 在dispatch找到重装的request
def dispatch(self, request, *args, **kwargs):
request = self.initialize_request(request, *args, **kwargs)
***这里开始找data
3 在initialize_request中找到实例request的类Request()
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
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
)
得到类对象Request(),注意parsers=self.get_parsers()后面会回来找
4 Request()中找到data方法
5 在data方法中--关注返回值
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
由于返回值默认:self._full_data = Empty
所以self._load_data_and_files()应该对_full_data进行复制了
6 从_load_data_and_files()找到_full_data
def _load_data_and_files(self): if not _hasattr(self, '_data'):
self._data, self._files = self._parse()
if self._files:
self._full_data = self._data.copy()
self._full_data.update(self._files)
else:
self._full_data = self._data
这里我们把self._parse()的结果分别复制给了self._data, self._files,且都放在了_full_data中,接下来观察self._parse()都给了什么值
7 _parse()
def _parse():
parser = self.negotiator.select_parser(self, self.parsers)
parsed = parser.parse(stream, media_type, self.parser_context)
empty_files = MultiValueDict()
return (parsed, empty_files)
parsed通过parser获取,而传入的参数中的self.parsers,就是我们初始化Request()中传入的参数parsers=self.get_parsers() // *****这里开始开始和parser_classes我们的设置解析数据类型设置相关了
8 我们回到步骤3找到parsers=self.get_parsers()
9 在get_parsers()中
return [parser() for parser in self.parser_classes]
得到从self.parser_classes中循环的列表
// *****选择从调用的视图类中获取parser_classes,没有从APIView中获取parser_classes
10 在APIView中获取到parser_classes
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
11 从api_settings查找DEFAULT_PARSER_CLASSES方法或属性
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
@property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings
class APISettings():
def __init__(defaults=None):
self.defaults = defaults or DEFAULTS
# 这里将DEFAULTS字典放在实例对象中,
def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr) try:
# Check if present in user settings
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
self.defaults = defaults or DEFAULTS --》这里将DEFAULTS字典放在实例对象中,我们发现DEFAULT_PARSER_CLASSES
就在字典中
由于没有DEFAULT_PARSER_CLASSES方法,我们执行__getattr__方法
1***** val = self.user_settings[attr]优先从配置中找有没有配置的路由解析方法,如果没配置
2***** val = self.defaults[attr]从实例化对象的内存空间中找方法
3 val = perform_import(val, attr)将'rest_framework.parsers.JSONParser'转化成JSONParser
解析器顺序
当前访问视图类下------------》全局settings---------》默认default
使用
# 设置全局解析方式
REST_FRAMEWORK={
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
),
}
# 当前访问视图类下设置解析方式
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView class LoginView(APIView):
parser_classes = [JSONParser]
def get(self,request):
print('get')
return render(request,'login.html')
def post(self,request):
print('body',request.body)
print(request.data)
print('data',request.data)
# print('POST', request.POST)
return HttpResponse('OK')
# 默认使用的解析方式
class APIView(View):
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
DRF-解析器组件源码解析的更多相关文章
- rest_framework解析器组件源码流程
rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...
- DRF之认证组件源码解析
认证组件 认证的几种方法:cookie,session,token几种.但是session会使服务器的压力增大,所以我们经常使用的是token.获取唯一的随机字符串: 登陆携带token值的处理: ...
- abp vnext2.0核心组件之领域实体组件源码解析
接着abp vnext2.0核心组件之模块加载组件源码解析和abp vnext2.0核心组件之.Net Core默认DI组件切换到AutoFac源码解析集合.Net Core3.1,基本环境已经完备, ...
- Spring 源码解析之DispatcherServlet源码解析(五)
spring的整个请求流程都是围绕着DispatcherServlet进行的 类结构图 根据类的结构来说DispatcherServlet本身也是继承了HttpServlet的,所有的请求都是根据这一 ...
- AQS源码解析(一)-AtomicBoolean源码解析
基本类: AtomicInteger AtomicLong AtomicBoolean 数组类型: AtomicIntegerArray AtomicLongArray AtomicReference ...
- 【源码解析】- ArrayList源码解析,绝对详细
ArrayList源码解析 简介 ArrayList是Java集合框架中非常常用的一种数据结构.继承自AbstractList,实现了List接口.底层基于数组来实现动态容量大小的控制,允许null值 ...
- Flink Sql 之 Calcite Volcano优化器(源码解析)
Calcite作为大数据领域最常用的SQL解析引擎,支持Flink , hive, kylin , druid等大型项目的sql解析 同时想要深入研究Flink sql源码的话calcite也是必备 ...
- JAVA常用集合源码解析系列-ArrayList源码解析(基于JDK8)
文章系作者原创,如有转载请注明出处,如有雷同,那就雷同吧~(who care!) 一.写在前面 这是源码分析计划的第一篇,博主准备把一些常用的集合源码过一遍,比如:ArrayList.HashMap及 ...
- 源码解析之AQS源码解析
要理解Lock首先要理解AQS,而要理解并发类最好的方法是先理解其并发控制量不同值的含义以及该类运作流程,然后配合一步步看源码.该类有一个重要的控制量是WaitStates,节点的状态值. /** w ...
随机推荐
- 【C#】上机实验一
1.开发一个控制台应用程序,根据提示从键盘获取一个华氏温度,请转换并输出对应的摄氏温度. using System; namespace Project { class Program { publi ...
- Scratch运动模块——有趣的弹球游戏(一)
大家好!我是蓝老师,有了前几期Scratch的基础,相信大家早已摩拳擦掌,跃跃欲试了,甚至还有些小伙伴已经编写了非常不错的程序. 学习编程就是这样不断探索.主动思考.解决问题的过程. 本期内容: 课程 ...
- 22-MySQL DBA笔记-其他产品的选择
第22章 其他产品的选择 本章将为读者介绍其他的数据库产品,主要是NoSQL产品的选择.读者在熟悉MySQL之外,也应该了解其他的数据库产品.本章的目的是给读者一个引导,如何选择一些NoSQL产品,而 ...
- 利用Filter和HttpServletRequestWrapper实现请求体中token校验
先说一下项目的背景,系统传参为json格式,token为其中一个必传参数,此时如果在过滤器中直接读取request,则后续controller中通过RequestBody注解封装请求参数是会报stre ...
- (一)Spring框架基础
一.什么是spring框架 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,i ...
- JS OOP -03 JS类的实现
JS类的实现: a.理解类的实现机制 b.使用prototype对象定义类成员 c.一种JS类的设计模式 a.理解类的实现机制 在JS中可以使用function关键字来定义一个类. 添加类的成员,在函 ...
- Java 面向对象(六)接口
一.接口 接口:是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量.构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(J ...
- struct 和class到底有什么区别
我们知道struct是C语言的宠儿,当需要一个复杂类型的时候就需要定义一个struct 比如一个学生结构体,含有三个属性,分别是编号.名字和年龄. typedef struct Student { i ...
- BP神经网络—java实现
神经网络的结构 神经网络的网络结构由输入层,隐含层,输出层组成.隐含层的个数+输出层的个数=神经网络的层数,也就是说神经网络的层数不包括输入层.下面是一个三层的神经网络,包含了两层隐含层,一个输出层. ...
- skeleton directory: /etc/skel
第一次接触这个词汇 还是在LFS8.2里面,感觉有点吓人.好好一个计算机操作系统,怎么搞出这个恐怖的术语.... 当使用useradd 或者其他命令创建用户的时候,/etc/skel这个目录下的文件. ...