解析器组件源码解析

解析器组件源码解析
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-解析器组件源码解析的更多相关文章

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

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

  2. DRF之认证组件源码解析

    认证组件  认证的几种方法:cookie,session,token几种.但是session会使服务器的压力增大,所以我们经常使用的是token.获取唯一的随机字符串: 登陆携带token值的处理: ...

  3. abp vnext2.0核心组件之领域实体组件源码解析

    接着abp vnext2.0核心组件之模块加载组件源码解析和abp vnext2.0核心组件之.Net Core默认DI组件切换到AutoFac源码解析集合.Net Core3.1,基本环境已经完备, ...

  4. Spring 源码解析之DispatcherServlet源码解析(五)

    spring的整个请求流程都是围绕着DispatcherServlet进行的 类结构图 根据类的结构来说DispatcherServlet本身也是继承了HttpServlet的,所有的请求都是根据这一 ...

  5. AQS源码解析(一)-AtomicBoolean源码解析

    基本类: AtomicInteger AtomicLong AtomicBoolean 数组类型: AtomicIntegerArray AtomicLongArray AtomicReference ...

  6. 【源码解析】- ArrayList源码解析,绝对详细

    ArrayList源码解析 简介 ArrayList是Java集合框架中非常常用的一种数据结构.继承自AbstractList,实现了List接口.底层基于数组来实现动态容量大小的控制,允许null值 ...

  7. Flink Sql 之 Calcite Volcano优化器(源码解析)

    Calcite作为大数据领域最常用的SQL解析引擎,支持Flink , hive,  kylin , druid等大型项目的sql解析 同时想要深入研究Flink sql源码的话calcite也是必备 ...

  8. JAVA常用集合源码解析系列-ArrayList源码解析(基于JDK8)

    文章系作者原创,如有转载请注明出处,如有雷同,那就雷同吧~(who care!) 一.写在前面 这是源码分析计划的第一篇,博主准备把一些常用的集合源码过一遍,比如:ArrayList.HashMap及 ...

  9. 源码解析之AQS源码解析

    要理解Lock首先要理解AQS,而要理解并发类最好的方法是先理解其并发控制量不同值的含义以及该类运作流程,然后配合一步步看源码.该类有一个重要的控制量是WaitStates,节点的状态值. /** w ...

随机推荐

  1. SAS学习笔记30 SAS各种常用随机函数

    UNIFORM(seed) 产生(0,1)区域均匀分布随机数,乘同余发生器 RANUNI(seed) 产生(0,1)区域均匀分布随机数,素数模发生器 NORMAL(seed) 产生标准正态分布随机数, ...

  2. Centos7安装gitlab11 学习笔记之备份恢复及邮箱配置

    一.备份 修改配置文件 vim /etc/gitlab/gitlab.rb 默认路径为 # gitlab_rails['backup_path'] = "/var/opt/gitlab/ba ...

  3. 动手实现CNN卷积神经网络

    数据集采用的是手写数据集(http://yann.lecun.com/exdb/mnist/): 本文构建的CNN网络图如下: 像素点:28*28 = 784,55000张手写数字图片. # -*- ...

  4. XCode下在不同位置声明变量的用法(转)

    XCode下在不同位置声明变量的用法 方式一:直接在.h文件@interface中的大括号中声明. @interface Test : NSObject { NSString *str; // 私有变 ...

  5. Error:Unable to start the daemon process. This problem might be caused by incorrect configuration of

    我试了修改或者配置gradle文件没有成功解决的 ,所以试了这个解决方案 试了下这个是可以解决的. 变量名   _JAVA_OPTIONS 变量值   -Djava.net.preferIPv4Sta ...

  6. ip地址、域名、DNS、URL(即网址)的区别与联系

    域名和ip ================================================================ 我们也知道每一台机都有一个唯一ip地址, 特别难记,所以出 ...

  7. selenium重定向新窗口

    1.跳转新窗口 # 浏览器跳转新窗口后,selenium绑定新窗口 print('页面跳转后重新绑定selenium.') time.sleep(3) search_window = driver.c ...

  8. CodeForces 822C Hacker, pack your bags!

    题意 给出一些闭区间(始末+代价),选取两段不重合区间使长度之和恰为x且代价最低 思路 相同持续时间的放在一个vector中,内部再对起始时间排序,从后向前扫获取对应起始时间的最优代价,存在minn中 ...

  9. linux添加地址映射

  10. 【异常】java.sql.SQLException: Could not retrieve transaction read-only status from server Query

    1 详细异常 java.sql.SQLException: Could not retrieve transaction read-only status , ], [ChargingOrderRea ...