前言

  一般我们写完序列化以后,我们就会开始写视图了,drf中我们一般使用CBV的方式,也就是类视图的方式,最基础的我们会使用from rest_framework.views import APIViewAPIView继承自View,关于视图的详解,我们后续再细讲。本章介绍drf的请求生命周期

前置准备工作

我们先写一个视图类TestView,代码如下:

from rest_framework.views import APIView
from rest_framework.response import Response
class TestView(APIView):
def get(self, request, *args, **kwargs):
return Response("drf get ok")
def post(self, request, *args, **kwargs):
return Response("drf post ok")

注意:这里的Response必须是drf下的Response,不能是Django原生的HttpResponse或者是JsonResponse,否则会出错

接着,在urls.py中配置路由,如下

urlpatterns = [
path('test/', views.TestView.as_view(), name="Test"),
]

然后我们访问http://127.0.0.1:8000/drf/test/,会出现下图样式,代表请求成功



接着我们在接口工具中使用POST请求方式访问,返回结果如下:

"drf post ok"

以上2种访问方式都成功了,接下来我们分析其中的请求过程以及原理

请求生命周期分析

首先我们先从路由配置中看到views.TestView.as_view(),调用的是TestView类视图下的as_view方法,但是我们上面定义该方法的时候,没有重写as_view()方法,所以会调用父类APIView中的as_view方法,源码如下:

@classmethod
def as_view(cls, **initkwargs):
"""
Store the original class on the view function. This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
""" # 判断queryset是否是QuerySet对象
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation # 调用父类的as_view方法
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
# 禁用了csrf认证
return csrf_exempt(view)

通过这行代码view = super().as_view(**initkwargs),可以知道APIViewas_view方法也调用了父类Viewas_view方法,源码如下:

def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key)) def view(request, *args, **kwargs):
self = cls(**initkwargs)
# 如果有get属性,没有head属性,那么head就是get
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get # 初始化所有视图方法共享的属性
self.setup(request, *args, **kwargs) # 如果没有request属性,报异常
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
) # 返回一个`dispatch`方法
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs # take name and docstring from class
update_wrapper(view, cls, updated=()) # and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view

as_view方法返回的是viewview返回的是dispatch方法,dispatch方法也是调用的APIView下的dispatch方法,源码如下:

def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
# 初始化请求,返回的是Request对象
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate? try:
# 在调用方法处理程序之前运行任何需要发生的操作
self.initial(request, *args, **kwargs) # Get the appropriate handler method
# 获取request的请求方法
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) # 返回一个response响应对象
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response

dispatch返回一个response响应对象,得到请求的响应结果,返回给前台

总结

  1. url请求走的是APIViewas_view函数
  2. APIViewas_view调用父类(django原生)的as_view,还禁用了csrf认证
  3. 在父类的as_view中的dispatch方法请求走的又是APIViewdispatch
  4. 完成任务方法交给视图类函数处理,得到请求的响应结果,返回给前台

Django(47)drf请求生命周期分析的更多相关文章

  1. DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render

    DRF框架    全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...

  2. drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析

    admin后台注册model  一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...

  3. Django(35)Django请求生命周期分析(超详细)

    Django请求生命周期分析 1.客户端发送请求 在浏览器输入url地址,例如www.baidu.com,浏览器会自动补全协议(http),变为http://www.baidu.com,现在部分网站都 ...

  4. DRF 请求生命周期以及各模块解析

    目录 rest_framework框架的封装特点 原生Django与DRF比较 APIView 的请求生命周期 请求模块(request) 解析模块(parser_classes) 异常模块(exce ...

  5. Django简介,请求生命周期,静态文件配置

    Web框架 ​ Web框架(Web framework)是一种开发框架,用来支持动态网站.网络应用和网络服务的开发.这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方 ...

  6. drf框架概况-resful接口规范-请求模块-渲染模块-Postman-drf请求生命周期

    drf框架 全称:django-rest- framework 知识点: """ 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码-基于restful ...

  7. 3) drf 框架生命周期 请求模块 渲染模块 解析模块 自定义异常模块 响应模块(以及二次封装)

    一.DRF框架 1.安装 pip3 install djangorestframework 2.drf框架规矩的封装风格 按功能封装,drf下按不同功能不同文件,使用不同功能导入不同文件 from r ...

  8. Django框架深入了解_01(Django请求生命周期、开发模式、cbv源码分析、restful规范、跨域、drf的安装及源码初识)

    一.Django请求生命周期: 前端发出请求到后端,通过Django处理.响应返回给前端相关结果的过程 先进入实现了wsgi协议的web服务器--->进入django中间件--->路由f分 ...

  9. APIview的请求生命周期源码分析

    目录 APIview的请求生命周期源码分析 请求模块 解析模块 全局配置解析器 局部配置解析器 响应模块 异常处理模块 重写异常处理函数 渲染模块 APIview的请求生命周期源码分析 Django项 ...

随机推荐

  1. Redis深入理解

    Redis Redis的三种集群方式 主从复制 原理 从服务器连接主服务器,发送sync(同步)命令 主服务器接收到sync命令后,开始执行bgsave命令生成RDB文件并使用缓存区记录此后执行的所有 ...

  2. 代码安全丨第六期:XPath注入漏洞样例

    1.什么是XPath注入漏洞? XPath是一种用来在内存中导航整个XML树的语言,它使用路径表达式来选取XML文档中的节点或者节点集. XPath注入是指程序使用外部输入动态构造用于从XML数据库检 ...

  3. Mybatis一级缓存和结合Spring Framework后失效的源码探究

    1.在下面的案例中,执行两次查询控制台只会输出一次 SQL 查询: mybatis-config.xml <?xml version="1.0" encoding=" ...

  4. 数据结构(3):java使用数组模拟堆栈

    堆栈原理: 数组模拟堆栈: //数组模拟栈 class ArrayStack{ //栈顶 private int top = -1; private int maxSize; private int[ ...

  5. day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

    一.类的继承顺序 只要继承object类就是新式类 不继承object类的都是经典类 在python3 中所有的类都继承object类,都是新式类 在python2 中不继承object的类都是经典类 ...

  6. G - Number Transformation(BFS+素数)

    In this problem, you are given an integer number s. You can transform any integer number A to anothe ...

  7. Sass中连体符(&)的运用

    在CSS中,这种想法是无法实现的,但在Sass中,可以轻松的通过连体符&来实现.这也是我们今天要说的. 我们先来回忆一下,CSS中常见的一组样式: /*页面中链接的颜色*/ a {clolor ...

  8. hdu4280 最大流DINIC

    题意:       x最小的到x最大的点同一时间的最大运输量. 思路:       裸的最大流,不解释,注意一点,记得加上防爆栈. #pragma comment(linker, "/STA ...

  9. POJ2135 来回最短路(简单费用流)

    题意:       就是从1走到n然后再走回来,一条边只能走一次,要求路径最短. 思路:       比较水,可以直接一遍费用流,不解释了,具体的看看代码,敲这个题就是为了练 练手,好久不敲了,怕比赛 ...

  10. Linux中su、sudo、sudo -i的用法和区别

    sudo :暂时切换到超级用户模式以执行超级用户权限,提示输入密码时该密码为当前用户的密码,而不是超级账户的密码.缺点是每次执行超级用户权限都要在命令前加上 sudo ,优点是在当前终端再使用 sud ...