rest_framework解析器组件源码流程
rest_framework解析器组件源码流程
解析器顾名思义就是对请求体进行解析。为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数据格式,比如xml,所以需要解析这类数据格式就需要用到解析器(也可以将请求体拿到,然后利用其他模块进行解析)。
rest_framework解析器就是对你请求体中的数据进行反序列化、封装 把你的所有的请求数据都封装在request.data中 以后就在request.data中获取数据
源码分析
在APIView的dispatch方法中重新封装了request
request = self.initialize_request(request, *args, **kwargs) 执行initialize_request()方法,在该方法中,get_parsers用于获取解析器,并被封装到request.parsers中。
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(), #获取所有的解析器,封装到request.parsers中
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
进入get_parsers()源码
def get_parsers(self):
"""
Instantiates and returns the list of parsers that this view can use.
"""
return [parser() for parser in self.parser_classes] #列表生成式,返回解析器对象,self就是当前执行APIview的类
进入parser_classes源码
class APIView(View): # The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES #解析器全局配置
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
进入api_settings源码 api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)# api_settings是APISettings类实例化的对象
进入APISettings源码 寻找parser_classes,在api_settings中找不到DEFAULT_PARSER_CLASSES,所以在APISettings中找,还是找不到,所以运行__getattr__方法。
__getattr__函数的作用: 如果属性查找(attribute lookup)在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__函数, 如果没有定义这个函数,那么抛出AttributeError异常。
@property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings def __getattr__(self, attr): #找不到DEFAULT_PARSER_CLASSES,所以运行__getattr__函数
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
进入DEFAULTS源码
DEFAULTS是rest_framework的默认settings配置文件,是个大字典,其中就有解析请求头的解析器
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
),
当调用request.data获取请求数据时候将使用解析器,下面是request.data源码:
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files() #执行_load_data_and_files(),获取请求体数据获取文件数据
return self._full_data
进入_load_data_and_files()源码
def _load_data_and_files(self):
"""
Parses the request content into `self.data`.
"""
if not _hasattr(self, '_data'):
self._data, self._files = self._parse() #执行self_parse(),获取解析器,并对content_type进行解析,选择解析器,返回数据
if self._files: #判断文件流数据,存在则加入到self._full_data(也就是我们的request.data)中
self._full_data = self._data.copy() ,
self._full_data.update(self._files)
else:
self._full_data = self._data #不存在将无文件流的解析完成的数据赋值到self._full_data(request.data) # if a form media type, copy data & files refs to the underlying
# http request so that closable objects are handled appropriately.
if is_form_media_type(self.content_type):
self._request._post = self.POST
self._request._files = self.FILES
进入self._parse()源码
def _parse(self):
"""
Parse the request content, returning a two-tuple of (data, files) May raise an `UnsupportedMediaType`, or `ParseError` exception.
"""
media_type = self.content_type #获取请求头content-type
try:
stream = self.stream #获取请求体
except RawPostDataException:
if not hasattr(self._request, '_post'):
raise
# If request.POST has been accessed in middleware, and a method='POST'
# request was made with 'multipart/form-data', then the request stream
# will already have been exhausted.
if self._supports_form_parsing():
return (self._request.POST, self._request.FILES)
stream = None if stream is None or media_type is None:
if media_type and is_form_media_type(media_type):
empty_data = QueryDict('', encoding=self._request._encoding)
else:
empty_data = {}
empty_files = MultiValueDict()
return (empty_data, empty_files) parser = self.negotiator.select_parser(self, self.parsers) #选择解析器 if not parser:
raise exceptions.UnsupportedMediaType(media_type) try:
parsed = parser.parse(stream, media_type, self.parser_context) #执行解析器的parse方法
except Exception:
# If we get an exception during parsing, fill in empty data and
# re-raise. Ensures we don't simply repeat the error when
# attempting to render the browsable renderer response, or when
# logging the request or similar.
self._data = QueryDict('', encoding=self._request._encoding)
self._files = MultiValueDict()
self._full_data = self._data
raise # Parser classes may return the raw data, or a
# DataAndFiles object. Unpack the result as required.
try:
return (parsed.data, parsed.files)
except AttributeError:
empty_files = MultiValueDict()
return (parsed, empty_files)
rest_framework解析器组件源码流程的更多相关文章
- DRF-解析器组件源码解析
解析器组件源码解析 解析器组件源码解析 1 执行request.data 开始找重装的request中的data方法 2 在dispatch找到重装的request def dispatch(self ...
- Django admin组件源码流程
admin 组件 Django 自带的用户后台组件 用于用户便携的操作 admin 组件核心 启动 注册 设计url 启动核心代码 每个app 通过 apps.py 扫描 admin.py 文件 并执 ...
- Django的rest_framework的分页组件源码分析
前言: 分页大家应该都很清楚,今天我来给大家做一下Django的rest_framework的分页组件的分析:我的讲解的思路是这样的,分别使用APIview的视图类和基于ModelViewSet的视图 ...
- DRF之解析器组件及序列化组件
知识点复习回顾一:三元运算 三元运算能够简化我们的代码, 请看如下代码: # 定义两个变量 a = 1 b = 2 # 判断a的真假值,如果为True,则将判断表达式的前面的值赋给c,否则将判断表达 ...
- DRF 解析器组件
Django无法处理application/json协议请求的数据,即,如果用户通过application/json协议发送请求数据到达Django服务器,我们通过request.POST获取到的是一 ...
- Rest_Framework之认证、权限、频率组件源码剖析
一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...
- abp vnext2.0核心组件之领域实体组件源码解析
接着abp vnext2.0核心组件之模块加载组件源码解析和abp vnext2.0核心组件之.Net Core默认DI组件切换到AutoFac源码解析集合.Net Core3.1,基本环境已经完备, ...
- DjangoRestFramework 学习之restful规范 APIview 解析器组件 Postman等
DjangoRestFramework学习一之restful规范.APIview.解析器组件.Postman等 本节目录 一 预备知识 二 restful规范 三 DRF的APIView和解析器组件 ...
- day89 DjangoRsetFramework学习---restful规范,解析器组件,Postman等
DjangoRsetFramework学习---restful规范,解析器组件,Postman等 本节目录 一 预备知识 二 restful规范 三 DRF的APIView和解析 ...
随机推荐
- Linux文件的打包与压缩
打包命令: tar tar 的选项与参数非常的多!我们只讲几个常用的选项,更多选项您可以自行 man tar 查询罗! [root@www ~]# tar [-j|-z] [cv] [-f 创建的档名 ...
- ActiveMQ安装优化
ActiveMQ性能測试 http://m.blog.csdn.net/blog/brushli/41750615 1.下载ActiveMQ 官网:http://activemq.apache.org ...
- 蓝桥杯 第三届C/C++预赛真题(10) 取球游戏(博弈)
今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定: 每个人从盒子中取出的球的数目必须是:1 ...
- spring boot 整合kafka 报错 Exception thrown when sending a message with key='null' and payload=JSON to topic proccess_trading_end: TimeoutException: Failed to update metadata after 60000 ms.
org.springframework.kafka.support.LoggingProducerListener- Exception thrown when sending a message w ...
- ssh框架搭建出现的问题和解决
[说明]今天尝试从头开始搭建ssh 框架, 真心是有点不太容易,可能是第一次吧,之前都是小打小闹. 一:今日完成 搭建 Spring 环境 --> 然后搭建 Hibernate 环境 --> ...
- 转载别人的DLL DEll研究
昨日,编了个DLL和EXE来进行了下测试,exe通过lib静态联编dll,来调用它的导出类,当改变DLL中导出类的结构(eg.成员变量的顺序等),从新发布DLL而不从新联结编译EXE,就会造成错误的执 ...
- 【Trello】使用指南
一.谷歌浏览器插件推荐: Card Color Titles for Trello 在Card上现实标签的标题文字 Trellists: Trello Lists Master 允许展示和隐藏List ...
- Unix file types
w https://en.wikipedia.org/wiki/Unix_file_types A socket is a special file used for inter-process co ...
- Java 之单例设计模式
设计模式: 对问题行之有效的解决方式, 其实它是一种思想. 单例设计模式 解决的问题:就是可以保证一个类在内存中的对象唯一性. 即单个实例. 比如对于A 和 B 两个程序使用同一个配置信息对象时, A ...
- MySQL数据库的设计和表创建
首先,我们使用Navicat Premium编辑器创建一个用户,同时设置用户权限,MySQL默认有一个root用户,拥有最高权限 下面,我们先创建一个用户: ①CREATE USER 'aaa'@' ...