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

  1. DRF-解析器组件源码解析

    解析器组件源码解析 解析器组件源码解析 1 执行request.data 开始找重装的request中的data方法 2 在dispatch找到重装的request def dispatch(self ...

  2. Django admin组件源码流程

    admin 组件 Django 自带的用户后台组件 用于用户便携的操作 admin 组件核心 启动 注册 设计url 启动核心代码 每个app 通过 apps.py 扫描 admin.py 文件 并执 ...

  3. Django的rest_framework的分页组件源码分析

    前言: 分页大家应该都很清楚,今天我来给大家做一下Django的rest_framework的分页组件的分析:我的讲解的思路是这样的,分别使用APIview的视图类和基于ModelViewSet的视图 ...

  4. DRF之解析器组件及序列化组件

    知识点复习回顾一:三元运算 三元运算能够简化我们的代码,  请看如下代码: # 定义两个变量 a = 1 b = 2 # 判断a的真假值,如果为True,则将判断表达式的前面的值赋给c,否则将判断表达 ...

  5. DRF 解析器组件

    Django无法处理application/json协议请求的数据,即,如果用户通过application/json协议发送请求数据到达Django服务器,我们通过request.POST获取到的是一 ...

  6. Rest_Framework之认证、权限、频率组件源码剖析

    一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...

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

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

  8. DjangoRestFramework 学习之restful规范 APIview 解析器组件 Postman等

    DjangoRestFramework学习一之restful规范.APIview.解析器组件.Postman等 本节目录 一 预备知识 二 restful规范 三 DRF的APIView和解析器组件 ...

  9. day89 DjangoRsetFramework学习---restful规范,解析器组件,Postman等

     DjangoRsetFramework学习---restful规范,解析器组件,Postman等           本节目录 一 预备知识 二 restful规范 三 DRF的APIView和解析 ...

随机推荐

  1. MySQL服务停止,无法启动了~

    怎么解决mysql服务无法启动的问题

  2. DataContract 和 DataMember

    数据契约(DataContract) 服务契约定义了远程访问对象和可供调用的方法,数据契约则是服务端和客户端之间要传送的自定义数据类型. 一旦声明一个类型为DataContract,那么该类型就可以被 ...

  3. C#中单例的双重锁定模式

    from:https://blog.csdn.net/sinat_20559947/article/details/48311915 using System; using System.Collec ...

  4. uva 1478 - Delta Wave(递推+大数+卡特兰数+组合数学)

    option=com_onlinejudge&Itemid=8&category=471&page=show_problem&problem=4224" st ...

  5. Eclipse Android 代码自己主动提示功能

    Eclipse Android 代码自己主动提示功能 Eclipse for android 实现代码自己主动提示智能提示功能.介绍 Eclipse for android 编辑器中实现两种主要文件 ...

  6. postgresql常用

    postgresql 字符串转整数 int.integer --把'1234'转成整数 select cast('1234' as integer ) ; --用substring截取字符串,从第8个 ...

  7. CodeForces 157B Trace

    B. Trace time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  8. ssh login waiting too much time

    usually dns error, please check /etc/resolv.conf

  9. Jconsole监控tomcat 的JVM内存的设置

    主要参考这位仁兄的文章  http://elf8848.iteye.com/blog/471676 照做后发现还是不行,原来是Linux服务器配置了多块网卡,在设置 Djava.rmi.server. ...

  10. 转!!Tomcat网站上的core和deployer的区别

    转自:https://www.cnblogs.com/guxia/p/6678184.html 8.5.13 Please see the README file for packaging info ...