一、一个请求来到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. 字符串string 、byte[]、MemoryStream、Base64String的相互转换

    1.字符串转比特数组 (1)byte[] bt=System.Text.Encoding.Default.GetBytes("字符串"); (2)byte[] bt=Convert ...

  2. 使用NOPI写入Excel基础代码

    using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.IO; using Sy ...

  3. winform中获取指定文件夹下的所有图片

    方法一: C#的IO自带了一个方法DirectoryInfo dir = new DirectoryInfo("文件夹名称");dir.getFiles();//这个方法返回值就是 ...

  4. [Linux] 搭建rsync服务端

    rsync是unix/linux下同步文件的一个高效算法,它能同步更新两处计算机的文件与目录,并适当利用查找文件中的不同块以减少数据传输. Linux守护进程的运行方式:1.独立运行(stand-al ...

  5. python学习笔记(十 三)、网络编程

    最近心情有点儿浮躁,难以静下心来 Python提供了强大的网络编程支持,很多库实现了常见的网络协议以及基于这些协议的抽象层,让你能够专注于程序的逻辑,而无需关心通过线路来传输比特的问题. 1 几个网络 ...

  6. Java开发笔记(七十七)使用Optional规避空指针异常

    前面在介绍清单用法的时候,讲到了既能使用for循环遍历清单,也能通过stream流式加工清单.譬如从一个苹果清单中挑选出红苹果清单,采取for循环和流式处理都可以实现.下面是通过for循环挑出红苹果清 ...

  7. Flask 系列之 Blueprint

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 学习如何使用 Blueprint 介绍 接触过 DotN ...

  8. weblogic Patch

    How to Apply WLS Patch on Weblogic Integrated with OEM Getting "Main Thread" Java.lang.Out ...

  9. 关于Keychain

    1.Keychain 浅析 2.iOS的密码管理系统 Keychain的介绍和使用 3.iOS开发中,唯一标识的解决方案之keyChain+UUID

  10. linux c ---raise 使用范例的代码

    把做工程过程中比较好的代码片段收藏起来,下面代码内容是关于linux c ---raise 使用范例的代码,希望对各位有所用途. #include <sys/types.h> #inclu ...