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 ...
随机推荐
- 【Manacher】Colorful String
The value of a string s is equal to the number of different letters which appear in this string. You ...
- c++学习总结(一)------类结构学习
基类的构造函数并没有被派生类继承 析构函数和拷贝赋值操作符同样也没有 类的设计者通过把成员函数声明为 const 以表明它们不修改类对象 把一个修改类数据成员的函数声明为 const 是非法的 (51 ...
- Luogu5284 十二省联考2019字符串问题(后缀树+拓扑排序)
对反串建SAM弄出后缀树,每个b串通过倍增定位其在后缀树上对应的节点,根据其长度将节点拆开.然后每个a串也找到对应的节点,由该节点向表示a串的节点连边,再把所给的边连上跑拓扑排序即可. #includ ...
- Mysql、Navicat Premium 12连接
1.配置MySQL80的环境 安装好MySQL,为MySQL配置环境变量.MySQL默认安装在C:\Program Files下. 1)新建MYSQL_HOME变量,并配置:C:\Program Fi ...
- py datetime
python datetime模块strptime/strptime format常见格式命令- [python]2011-12-23 版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本 ...
- XML-RPC-2RPC
远程过程调用协议 RPC一般指远程过程调用协议 RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协 ...
- kong 命令(五)plugin
介绍 plugin 插件 是运用在kong网关各模块的功能.在http请求或响应过程中执行的插件: 可以实现认证.负载.加密等功能. kong官网提供了一些插件:https://docs.konghq ...
- Pyhon中迭代器与生成器
迭代器 我们知道,可以直接用for循环的数据类型有以下几种: 一类是集合数据类型:list.tuple.dict.set.str等 一类是generator:包括生成器和带yield的generato ...
- jQuery动画速成
引入下面css中样式,然后在需要使用的元素中类上添加相应的效果就可以了 例如 animated固定要添加的类,不然会没有效果,bounceIn是你想要的动画效果,fight是你自己定义的类名,可以写样 ...
- AngularJS入门教程之与服务器(Ajax)交互操作示例
AngularJS从Web服务器请求资源都是通过Ajax来完成,所有的操作封装在$http服务中,$http服务是只能接收一个参数的函数,这个参数是一个对象,用来完成HTTP请求的一些配置,函数返回一 ...