侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

从请求到响应过程中django都做了哪些处理

框架(架构)  /  管理员 发布于 7年前   449

前言

最近面试的时候,被面试官问道一个问题,就是 request.user 里面的 user 是怎样得到的,这个问题当时没有回答上来,可以说是非常的尴尬,所以赶快查了一些资料,看了一些源码,特地来总结一下这个问题。

要想回答为什么可以直接通过 request.user 得到请求的用户,应该先来看看请求被处理以及如何返回响应的流程。今天先总结一下 django 从请求到响应都进行了哪些过程。

WSGI

当客户端发送一次请求后,最先处理请求的实际上是 web 服务器就是我们经常说的 nginx、Apache 这类的 web 服务器,而 WSGI 的作用就是把 web 服务器和 web 框架 (Django) 连接起来。WSGI 被分为了两个部分:服务端和应用端。为了处理一个 WSGI 的响应,服务端执行应用程序并向应用端提供一个回调函数,应用端处理请求并使用提供的回调将响应返回给服务端。

本质上来讲,我觉得 WSGI 就是 web 服务器和 django 应用之间的一个联系人。

数据流

当用户向你的应用发送一个请求的时候,一个 WSGI handler 将会被初始化,它会完成以下工作:

  1. 导入 settings.py 和 django 的异常类
  2. 使用 load_middleware 方法加载 settings.py 中 MIDDLEWARE_CLASSES 或者 MIDDLEWARES 元组中所用的 middleware classes.
  3. 创建四个列表 (_request_middleware,_view_middleware, _response_middleware, _exception_middleware),里面分别包含处理 request,view,response 和 exception 的方法。
  4. WSGI Handler 将实例化一个 django.http.HTTPRequest 对象的子类,django.core.handlers.wsgi.WSGIRequest.
  5. 循环遍历处理 request 的方法 (_request_middleware 列表),并按照顺序调用他们
  6. 解析请求的 url
  7. 循环遍历每个处理 view 的方法 (_view_middleware 列表)
  8. 如果找的到的话,就调用视图函数
  9. 处理任何异常的方法 (_exception_middleware 列表)
  10. 循环遍历每个处理响应的方法 (_response_middleware 列表),(从内向外,与请求中间件的顺序相反)
  11. 最后得到一个响应,并调用 web server 提供的回调函数

中间件

中间件被用在了 django 的许多关键功能中:例如,使用 CSRF 中间键来防止跨站请求伪造攻击。它们也被用来处理会话数据,身份认证和授权同样是由中间件来完成的。我们也可以自己编写中间件来调整或者(短路)通过应用程序的数据流。

django 的中间件至少含有以下四个方法中的一个:process_request, process_response, process_view, process_exception。这些方法会被 WSGI handler 收集并按照顺序调用。

process_request

我们可以先来看看 django.contrib.auth.middleware.AuthenticationMiddleware:

def get_user(request): if not hasattr(request, '_cached_user'):  request._cached_user = auth.get_user(request) return request._cached_userclass AuthenticationMiddleware(MiddlewareMixin): def process_request(self, request):  assert hasattr(request, 'session'), (    "The Django authentication middleware requires session middleware "    "to be installed. Edit your MIDDLEWARE%s setting to insert "    "'django.contrib.sessions.middleware.SessionMiddleware' before "    "'django.contrib.auth.middleware.AuthenticationMiddleware'."  ) % ("_CLASSES" if settings.MIDDLEWARE is None else "")  request.user = SimpleLazyObject(lambda: get_user(request))

这里我们可以发现 request.user 这个属性是在 AuthenticationMiddleware 中产生的。这个我们稍后再说。

这里我们可以发现,这个中间件只有 process_request,说明它只在 request 这一步处理流入和流出 django 应用的数据流。这个中间件会首先验证会话中间件是否被使用,然后通过调用 get_user 函数来设置用户。当 WSGI 处理程序迭代

process_request 方法列表的时候,它将会构建这个最终会被传递给视图函数的请求对象,并能够使你引用 request.user。一些中间件没有 process_request 方法,在这个阶段,会被跳过。

process_request 应该返回 None 或者 HTTPResponse 对象。当返回 None 时,WSGI handler 会继续加载 process_request 里面的方法,但是后一种情况会短路处理过程并进入 process_response 循环。

解析 url

当所有的 process_request 被调用完之后,我们就会得到一个将被传递给视图函数的 request 对象。当这个事件发生之前,django 必须解析 url 并决定调用哪一个视图函数。这个过程非常简单,只需要使用正则匹配即可。settings.py 中有一个 ROOT_URLCONF 键来指定根 url.py,在这里会包含你所有 app 的 urls.py 文件。如果没有匹配成功,将会抛出一个异常 django.core.urlresolvers.Resolver404, 这是 django.http.HTTP404 的子类。

process_view

到这一步之后 WSGI handler 知道了调用哪一个视图函数,以及传递哪些参数。它会再一次调用中间件列表里面的方法,这次是_view_middleware 列表。所有 Django 中间件的 process_view 方法将会被这样声明:

process_view(request, view_function, view_args, view_kwargs)

和 process_request 一样,process_view 函数必须返回 None 或者 HTTPResponse 对象,使得 WSGI handler 继续处理视图或者'短路'处理流程并返回一个响应。在 CSRF middleware 中存在一个 process_view 的方法。作用是当 CSRF cookies 出现时,process_view 方法将会返回 None, 视图函数将会继续的执行。如果不是这样,请求将会被拒绝,处理流程将会被'短路',会生成一个错误的信息。

进入视图函数

一个视图函数需要满足三个条件:

  • 必须是可以调用的。这可以是基于函数的视图或者是 class-based 的视图(继承自 View 并且使用 as_view() 方法来使它成为可调用的。这些方法的调用依赖 HTTP verb(GET, POST, etc))
  • 必须接受一个 HTTPRequest 对象作为第一个位置参数。这个 HTTPRequest 对象是被所有 process_request 和 process_view 中间件方法处理的结果。
  • 必须返回一个 HTTPResponse 对象,或者抛出一个异常。就是用这个 response 对象来开启 WSGI handler 的 process_view 循环。

process_exception

如果视图函数抛出一个异常,Handler 将会循环遍历_exception_middleware 列表,这些方法按照相反的顺序执行,从 settings.py 里面列出来的最后一个中间件到第一个。如果一个异常被抛出,处理过程将会被短路,其他的 process_exception 将不会被执行。通常我们依赖 Djnago's BaseHandler 提供的异常处理程序,但是我们也可以使用自定义的异常处理中间件。

process_response

在这个阶段,我们得到了一个 HTTPResponse 对象,这个对象可能是 process_view 返回的,也可能是视图函数返回的。现在我们将循环访问响应中间件。这是中间件调整数据的最后的机会。执行的顺序是从内向外执行。

以 cache middleware 的 process_response 为例:它依赖于你的 app 里面的不同的状态(缓存是否打开或者关闭,是否在处理一个数据流),来决定是否缓存你的响应。

注意

django 1.10 和之前版本的区别:

在旧版本的 MIDDLEWARE_CLASSES 中,就算一个中间件”短路”了执行过程,所有的中间件都会调用它们的 process_response 方法。而在新的 MIDDLEWARES 版本中,只有这个中间件和在它之前执行的中间件才会调用 process_response 方法。

总结

以上就是 django 在处理一个请求的基本的过程,最后 django 的 WSGI Handler 会创建一个来自 HTTPResponse 的返回值,而且会调用回调函数把数据传递给 web server, 最后返回给用户。

以下是两个关键点:

我们现在知道了视图函数是如何和 url 解析器匹配以及什么在调用它 (WSGI Handler)

有四个关键的地方可以让你挂钩到请求 / 响应周期:process_request, process_response, process_view, process_exception。请求中间件是从外部向内执行,最后抵达到视图函数,然后通过响应中间件从内向外返回。

参考资料

  • Django Middlewares and the Request/Response Cycle
  • How Django processes a request

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对AIDI的支持。


  • 上一条:
    django从请求到响应的过程深入讲解
    下一条:
    Django进阶之CSRF的解决
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Filament v3.1版本发布(0个评论)
    • docker + gitea搭建一个git服务器流程步骤(0个评论)
    • websocket的三种架构方式使用优缺点浅析(0个评论)
    • ubuntu20.4系统中宿主机安装nginx服务,docker容器中安装php8.2实现运行laravel10框架网站(0个评论)
    • phpstudy_pro(小皮面板)中安装最新php8.2.9版本流程步骤(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2018-05
    • 2020-02
    • 2020-03
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-11
    • 2021-03
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-08
    • 2023-08
    • 2023-10
    • 2023-12
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客