一、一个请求来到Django 的生命周期
  • FBV 不讨论

  • CBV:

    请求被代理转发到uwsgi:

    开始Django的流程:

    首先经过中间件process_request (session等)

    然后:url --- > Xxx.as_view() 根据url映射到对应业务逻辑类 --->process_view (csrf等)

     

    业务逻辑类中:

    as_view() -- > view ---> dispatch() 通过映射调用请求的方法在业务逻辑中的对应处理函数

    (如post、put、delete等)

 

1.2 CBV源码解析
  • 自己的业务逻辑类:MyView 继承View

  • 没有as_view() 方法,将会去父类View找as_view

class MyView(View):

    def get(self, request):
#处理业务逻辑,返回response
pass def post(self, request):
pass def put(self, request):
pass def delete(self, request):
pass

 

1.2.2 View源码中:as_view() 方法被调用
  • 查看as_view 方法源码:作者省略了部分,只留下了关键部分,并做了注释
class View:
...
@classonlymethod
def as_view(cls, **initkwargs):
... def view(request, *args, **kwargs):
...
return self.dispatch(request, *args, **kwargs) #调用父类的dispatch() 方法
... return view #返回内部定义的view 方法

这儿可以看见:

1.  as_view()方法被调用,

2.  内部回返回定义的view 方法,

3.  view方法中调用了 dispatch() 方法

4.  如果自己的类没有重写dispatch 方法的话,将会调用父类View类的 dispatche() 方法

 

1.2. 查看dispatch方法
  • dispatch方法中:作者省略了部分,只留下了关键部分,并做了注释
class View:
...
def dispatch(self, request, *args, **kwargs):
...
#request.method中保存了客户端解析出来的请求方法,如:GET/POST等
if request.method.lower() in self.http_method_names: #通过映射找到请求对应我们自己的业务逻辑处理函数
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) #并调用该业务逻辑函数处理结果,将结果返回
  • 注意:request.method 保存着解析出来的请求行第一个数据(GET URL HTTP1.1)如:GET

可以看见:

1.  if判断客户端请求的方法是否是,http协议(Django)自己支持的

2.  handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

    将请求方法小写,然后在自己的业务类中映射到对应处理函数,如果没有报错

3.  return handler(request, *args, **kwargs)

    并调用该业务逻辑函数处理结果,将结果返回

 

二、rest_framework APIView 流程解析

先看一个图:给出大致流程

 

2.2 APIView中请求流程
  • 同上:请求通过URL 匹配到继承APIView的自己的业务逻辑类。
class APIView(View):
...
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 #权限类
...
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS #版本控制获取类 ... @classmethod
def as_view(cls, **initkwargs):
...
view = super(APIView, cls).as_view(**initkwargs) #继承父类as_view方法
view.cls = cls
view.initkwargs = initkwargs
...
return csrf_exempt(view) #返回父类view
...
def get_parsers(self):
"""
获取到上面4. 第一步initialize_request函数封装request过程中一并生成封装的解析器对象
"""
return [parser() for parser in self.parser_classes] def get_authenticators(self):
"""
同理身份认证对象
"""
return [auth() for auth in self.authentication_classes] def get_permissions(self):
"""
同理权限对象
"""
return [permission() for permission in self.permission_classes] def get_throttles(self):
"""
同理限流(访问频率控制对象)
"""
return [throttle() for throttle in self.throttle_classes] def perform_authentication(self, request):
... #这里面真正认证 def check_permissions(self, request):
... #这里面检查权限 def check_throttles(self, request):
... #这里面限流 def determine_version(self, request, *args, **kwargs):
... #这里面获取版本 def initialize_request(self, request, *args, **kwargs):
"""
被dispatch调用,封装request,并调用上述函数生成相应对象封装到request对象中
"""
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
) def initial(self, request, *args, **kwargs):
...
被dispatch调用,在里面初始化获取版本,认证、权限检查、访问控制等 # Determine the API version, if versioning is in use.
#处理版本问题,调用 determine_version方法
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
#3.在这儿实现认证
self.perform_authentication(request)
#4.权限检查
self.check_permissions(request)
#5.访问频率控制 ... def dispatch(self, request, *args, **kwargs):
...
self.args = args
self.kwargs = kwargs
##############################################################
# 1.封装request
request = self.initialize_request(request, *args, **kwargs)
##############################################################
self.request = request
self.headers = self.default_response_headers # deprecate? try:
##############################################################
#2.认证
self.initial(request, *args, **kwargs)
##############################################################
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc:
response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response

如下步骤对应上述省略部分的源代码去找:

1. 找as_view()函数

第一步自己业务逻辑类中:没有,

第二步父类-APIView中:找到as_view方法,开始调用

2. APIView继承了View,APIView的as_view函数继承了父类as_view:如下为源码

view = super(APIView, cls).as_view(**initkwargs) #继承父类的as_view

view.cls = cls #把自身封装进去

view.initkwargs = initkwargs #将参数初始化

return csrf_exempt(view) #返回view

可以看见封装了一次as_view方法,将自身cls (APIView)一起封装到了view中

并返回

3. 通过上面1-2 知道:继承请求进入后会调用返回的view方法,然后在self中找dispatch方法,

第一步自己的业务逻辑类中:没有dispatch

第二步父类APIView中:找到dispatch方法,开始调用

4. APIView的dispatch 函数中:

第一步:request = self.initialize_request(request, *args, **kwargs) 封装了一次request

 

initialize_request函数内如下:

return Request(

request, #原生request

parsers=self.get_parsers(), #解析器

authenticators=self.get_authenticators(), #身份验证器

negotiator=self.get_content_negotiator(),

parser_context=parser_context

)

第二步:self.initial(request, *args, **kwargs) 开始初始化认证

 

initial函数内:

1)获取版本,版本处理类实例。并封装到request中

version, scheme = self.determine_version(request, *args, **kwargs)

request.version, request.versioning_scheme = version, scheme

 

2)身份(登录)认证啥的

self.perform_authentication(request)

 

3)权限管理

self.check_permissions(request)

 

4)限流控制(访问频率控制)

self.check_throttles(request)

 

2.2.3 上述总结
  1. 首先找dispatch 函数(APIView类中)

  2. dispatch中:

    调用了self.initialize_request 函数封装request

  3. 接着2的dispatch中initialize_request 函数

    查看APIView中的initialize_request 函数

    调用了:get_parsers()、get_authenticators() 等

    封装了一堆解析器类实例、认证类实例啥的

    可自己去看(这些类使用默认配置,APIView 一开头下面一堆配置就是)

    这些类也可以自己写,配置到自己的业务逻辑类中,或者settings.py中作为全局配置(下面在讲)

  4. 接着2的dispatch中initial函数

    版本获取:

    version, scheme = self.determine_version(request, *args, **kwargs)

    request.version, request.versioning_scheme = version, scheme

    实现认证

    self.perform_authentication(request)

    权限检查

    self.check_permissions(request)

    访问频率控制

    self.check_throttles(request)

 

三、常用的解析、认证、权限、访问频率控制源码及解析

from rest_framework.views import APIView #继承类路径

from rest_framework import request #dispatch中initialize_request封装的request对象

from rest_framework.parsers import JSONParser, FormParser, FileUploadParser #不同解析器

from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning #两种版本获取器

from rest_framework.authentication import BaseAuthentication #登录验证

from rest_framework.permissions import BasePermission #权限

from rest_framework.throttling import SimpleRateThrottle #节流

from rest_framework import exceptions #错误

Django生命周期 URL ----> CBV 源码解析-------------- 及rest_framework APIView 源码流程解析的更多相关文章

  1. Django生命周期,FBV,CBV

    一. Django生命周期 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串,在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中.Django的请求生命周 ...

  2. 学以致用三十三-----django生命周期

    听了讲解django的视频后,受益匪浅,每个知识点老师都会总结整理.学会总结,存为己用. django生命周期弄明白后,对于整个django的框架会有一个清晰的了解.先上图 1.客户端发送请求,在dj ...

  3. 用户增删改查 django生命周期 数据库操作

    一 django生命周期 1 浏览器输入一个请求(get/post)2 响应到django程序中3 执行到url,url通过请求的地址匹配到不同的视图函数4 执行对应的视图函数,此过程可以查询数据库, ...

  4. django生命周期和事件委派

    这是事件委派如果不用事件委派   直接绑定的话,新添加的按钮不会有删除或者编辑的功能 上面是事件委派的代码 新添加的编辑按钮可以弹出123 django生命周期: 这是Django的生命周期 首先会通 ...

  5. Django框架(三)-- orm增删改查、Django生命周期

    一.orm介绍 1.什么是orm ORM即Object Relational Mapping,全称对象关系映射. 2.使用orm的优缺点 优点: 不用写SQL语句 开发效率高 缺点: SQL的效率低 ...

  6. Django框架(三)—— orm增删改查、Django生命周期

    目录 orm增删改查.Django生命周期 一.orm介绍 二.orm增删改字段 三.Django生命周期 orm增删改查.Django生命周期 一.orm介绍 1.什么是orm ORM即Object ...

  7. 【Cocos2d-x 3.x】 场景切换生命周期、背景音乐播放和场景切换原理与源码分析

    大部分游戏里有很多个场景,场景之间需要切换,有时候切换的时候会进行背景音乐的播放和停止,因此对这块内容进行了总结. 场景切换生命周期 场景切换用到的函数: bool Setting::init() { ...

  8. Django生命周期

    以下信息是个人理解所得,如要转载,请注明转载处! 生命周期?很多人会问生命周期是什么?Django也有生命周期吗?他就是一个框架呀. 我们先来说一说一个西瓜的生命周期,一个西瓜刚开始只是一个种子,种到 ...

  9. Django(十一)请求生命周期之CBV与FBV

    https://www.cnblogs.com/yuanchenqi/articles/8715364.html FBV FBV(function base views) 就是在视图里使用函数处理请求 ...

随机推荐

  1. [VsCode] 开发所使用的VsCode的插件

    vscode 的插件 必须 Chinese (Simplified) Language Pack for Visual Studio Code Markdown Preview Enhanced De ...

  2. 【.NET Core项目实战-统一认证平台】第八章 授权篇-IdentityServer4源码分析

    [.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何在网关上实现客户端自定义限流功能,基本完成了关于网关的一些自定义扩展需求,后面几篇将介绍基于IdentityServer ...

  3. Creating a ROS msg and srv

    msg: msg files are simple text files that describe the fields of a ROS message. They are used to gen ...

  4. Linux-Kconfig总结与分析

    使用Kconfig时,需要注意的地方 1.在Kconfig中定义的配置宏,前缀都没有"CONFIG_",只有编译内核时,自动生成autoconf.h才会出现前缀. 2.如果XX_d ...

  5. JS最简单的字符串转数字类型

    以前无休止的写parseInt,特别复杂,现在只需要一个加号,就可以完成对字符串的转换 1 === +"1" amazing!

  6. CentOS6.9升级autoconf版本,解决”Autoconf version 2.64 or higher is required“错误

    安装软件时提示说需要Autoconf 2.64或更高的版本: # autoconf configure.ac:: error: Autoconf version 2.64 or higher is r ...

  7. 42.Odoo产品分析 (四) – 工具板块(10) – 问卷(2)

    查看Odoo产品分析系列--目录 接上一篇Odoo产品分析 (四) – 工具板块(10) – 问卷(1) 4 页面 即问卷,点开一项查看:  可以看出,网页就是问卷本身的子目录,其中指明了该目录包括哪 ...

  8. Python第十一天 异常处理 glob模块和shlex模块 打开外部程序和subprocess模块 subprocess类 Pipe管道 operator模块 sorted函数 os模块 hashlib模块 platform模块 csv模块

    Python第十一天    异常处理  glob模块和shlex模块    打开外部程序和subprocess模块  subprocess类  Pipe管道  operator模块   sorted函 ...

  9. aspnetcoremodule 2.1下载

    下载地址 or 云盘 aspnetcoremodule 2.1 页面地址 下载地址 云盘下载 链接:https://pan.baidu.com/s/1YKYzpP7E__yXQKpOVrN6nw 密码 ...

  10. SQL 创建分区表

    (以项目中实际使用的GNSS库为例) 背景:数据量巨大,定时创建月表存放数据,月表中数据存放在不同的文件组中来提高查询效率   一.创建数据库,添加文件组 除了逻辑文件和物理文件的分离之外,SQL S ...