您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

Django中间件看完这篇彻底明白

时间:2020-03-20 10:28:21  来源:  作者:

我们在使用Python的一些库时,会遇到中间件这个概念,比如scrapy和Django,那么什么是中间件呢?

什么是中间件

中间件就是在目标结果之间进行的额外处理过程,在Django中就是request和response之间进行的处理,相对来说实现起来比较简单,但是要注意它是对全局有效的,可以在全局范围内改变输入和输出结果,因此需要谨慎使用,否则不仅会造成难以定位的错误,而且可能会影响整体性能。

中间件有什么用

如果想要修改HttpRequest或者HttpResponse,就可以通过中间件来实现。

  • 登陆认证:在中间件中加入登陆认证,所有请求就自动拥有登陆认证,如果需要放开部分路由,只需要特殊处理就可以了。
  • 流量统计:可以针对一些渲染页面统计访问流量。
  • 恶意请求拦截:统计IP请求次数,可以进行频次限制或者封禁IP。

中间件执行流程

在Django中自定义中间件是非常简单的,在settings.py中有一个配置项:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

只要把添加的中间件配置在这里就可以了。每一个中间件都是一个类,多个中间件可以写在同一个文件,也可以在独立文件中。每个中间件可以包含五个方法:

process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

我在网上找到这么一张图片,说明了请求的数据流在Django中间件当中的执行流程

Django中间件看完这篇彻底明白

 

中间件函数执行流程

  • 请求到达中间件后先依次执行每个中间件的process_request函数
  • 然后再依次执行每个中间件的process_view函数,找到我们的视图函数
  • 执行视图函数处理请求数据
  • 如果在上面的过程中出现异常,则依次反方向执行每个中间件的process_exception函数
  • 如果请求包含模板渲染,则依次反方向执行每个中间件的process_template_response函数
  • 最后依次反方向执行每个中间件的process_response函数

以上这些执行函数将返回None或者HttpResponse对象,如果返回None,则交给下一个中间件的对应函数处理;如果返回HttpResponse对象,则将其返回给用户

在这些中间件的执行函数中,我们最常用的就是process_request和process_response函数,通常用来在视图函数处理前和视图函数处理后执行一些相应的操作,这个要根据我们的业务需求,选择不同的处理过程。例如:进行登陆认证,因为必须要在视图函数处理前进行认证,我们可以在process_request中处理;携带认证cookies信息,就可以在process_response函数中给response对象增加指定cookies值。

中间件回调函数执行

  • Request函数:process_request(self, request)
    执行时机:当接收到前端请求,并生成request对象,但是仍未解析url,未确定当前要运行的视图函数。
    如果返回None,Django将继续处理下一个中间件的request函数;如果返回HttpResponse对象,Django将不再执行其他除process_response以外的所有函数,包括后面的process_request函数其他中间件函数以及视图函数
  • View函数:process_view(self, request, callback, callback_args, callback_kwargs)
    执行时机:在执行完所有中间件的process_request函数,并且已经匹配到要执行的视图函数,但是还没有调用视图函数之前。
    callback:时机要执行的视图函数对象(就是我们所写的视图处理函数)
    callback_args:视图函数的位置参数列表(不包含self和request)
    callback_kwargs:视图函数的关键字参数
    如果返回None,Django将继续处理下一个中间件的request函数;如果返回HttpResponse对象,Django将不再执行其他除process_response以外的所有函数,包括后面的process_request函数其他中间件函数以及视图函数
  • Template函数:process_template_response()
    执行时机:只有在视图函数的返回对象中有render方法才会执行,并把render方法的返回值返回给用户。
  • Exception函数:process_exception(self, request, exception)
    执行时机:如果在执行过程中出现问题,并且抛出一个未被捕获的异常时才被调用。我们可以用它来捕获请求错误,发送通知或者恢复错误场景。
    如果返回None,Django将使用框架内置异常处理,并继续交给下一个exception函数;如果返回HttpResponse对象,Django将不再执行其他除process_response以外的所有函数,并中断异常处理。
  • Response函数:process_response(self, request, response)
    执行时机:执行完view函数并生成response之后,几乎是必执行的函数。
    返回并且只能必须返回HttpResponse对象,否则会导致HTTP请求中断。

自定义中间件

  • 创建中间件类
from django.utils.deprecation import MiddlewareMixin

class MyCustomMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print('MyCustomMiddleware1')

    def process_response(self, request, response):
        print('返回 MyCustomMiddleware1')
        return response

class MyCustomMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print('MyCustomMiddleware2')

    def process_response(self, request, response):
        print('返回 MyCustomMiddleware2')
        return response
  • 注册中间件
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'MyMiddleware.MyCustomMiddleware1',
    'MyMiddleware.MyCustomMiddleware2'
]

输出结果:

MyCustomMiddleware1
MyCustomMiddleware2
返回 MyCustomMiddleware2
返回 MyCustomMiddleware1

系统中间件的用途

  • django.middleware.security.SecurityMiddleware主要是针对安全访问处理,就是把http请求重定向到https请求
  • django.contrib.sessions.middleware.SessionMiddleware在Django中我们用的request.session就是在process_request中进行处理的,根据我们在settings中配置的SESSION_COOKIE_NAME变量,从cookies中获取对应的值,从表中查询出session值,创建session对象,赋值给request_session对象。
def process_request(self, request):
    session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
    request.session = self.SessionStore(session_key)

process_response函数中,给response对象设置SESSION_COOKIE_NAME值和过期时间等。

response.set_cookie(
   settings.SESSION_COOKIE_NAME,
   request.session.session_key, max_age=max_age,
   expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
   path=settings.SESSION_COOKIE_PATH,
   secure=settings.SESSION_COOKIE_SECURE or None,
   httponly=settings.SESSION_COOKIE_HTTPONLY or None,
   samesite=settings.SESSION_COOKIE_SAMESITE
)
  • django.middleware.common.CommonMiddleware
    检测是否允许浏览器类型
if 'HTTP_USER_AGENT' in request.META:
    for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
        if user_agent_regex.search(request.META['HTTP_USER_AGENT']):
            raise PermissionDenied('Forbidden user agent')

检查是否需要添加/,主要是根据settings中AppEND_SLASH配置

if self.should_redirect_with_slash(request):
    path = self.get_full_path_with_slash(request)
else:
    path = request.get_full_path()

在process_response函数中,会判断是否需要把404的请求重新定向到我们需要的页面

  • django.middleware.csrf.CsrfViewMiddleware
    这个很明显就是我们Django框架的csrf验证了,主要是process_view中的处理,从函数处理我们可以看到以下几点:
  1. request请求中包含csrf_processing_done属性,则不进行csrf验证
  2. 视图函数中包含csrf_exempt属性,则不进行csrf验证
  3. 如果是GET、HEAD、OPTIONS、TRACE请求,则不进行csrf验证
  4. request请求中包含_dont_enforce_csrf_checks属性,则不进行csrf验证
  5. https请求头中如果不包含HTTP_REFERER,则拒绝访问
  6. 请求头中不包含CSRF_COOKIE,则拒绝访问
  7. POST请求中携带csrfmiddlewaretoken参数,如果验证通过就可以访问
  8. PUT/DELETE请求头中携带CSRF_HEADER_NAME配置,如果验证通过就可以访问
  • django.contrib.auth.middleware.AuthenticationMiddleware这个中间件中为我们的request对象添加了user属性,主要是获取session中SESSION_KEY值(settings配置中),从用户表中查询对应主键,得到用户对象,将其付给request.user
  • django.contrib.messages.middleware.MessageMiddlewareDjango的消息框架,主要是向目标中推送消息内容,在前端可通过以下方式使用
{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}" {% endif %}>
        {% if mesage.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
        {{ message }}
    </li>
    {% endfor %}
</ul>
{% endif %}


Tags:Django   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前几节课我们学习了Django加载网页数据的相关知识,今天我们讲一下怎么加载静态文件,我们以加载图片为例,学习怎么配置静态文件。 1.思路讲解 首先我们需要新建文件(test2)作为我...【详细内容】
2021-11-23  Tags: Django  点击:(43)  评论:(0)  加入收藏
在本教程中,我们将介绍如何使用 Django 发送电子邮件。我们将介绍如何配置 Django SMTP 连接,如何为您的电子邮件提供商设置应用程序密码,以及如何通过 Django shell 发送电子...【详细内容】
2021-11-10  Tags: Django  点击:(22)  评论:(0)  加入收藏
1. 安装python3.81.1 安装相关依赖包yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel li...【详细内容】
2021-10-13  Tags: Django  点击:(43)  评论:(0)  加入收藏
最近工作中需要开发前端操作远程虚拟机的功能,简称 WebShell。基于当前的技术栈为 react+django,调研了一会发现大部分的后端实现都是 django+channels 来实现 websocket 服务。...【详细内容】
2021-09-13  Tags: Django  点击:(52)  评论:(0)  加入收藏
一、MySQL主从搭建主从配置原理: 主库写日志到 BinLog 从库开个 IO 线程读取主库的 BinLog 日志,并写入 RelayLog 再开一个 SQL 线程,读 RelayLog 日志,回放到从库中主从配置流...【详细内容】
2021-08-03  Tags: Django  点击:(46)  评论:(0)  加入收藏
django 编写数据接口django-admin&bull;django-shell 新增文章太复杂&bull;创建管理员用户&bull;登陆页面进行管理创建超级用户python manage.py createsuperuser访问:http:/...【详细内容】
2021-06-16  Tags: Django  点击:(139)  评论:(0)  加入收藏
装饰器的作用(简而言之):让其他函数在不需要做任何代码变动的前提下增加额外的功能FBV加装饰器例:以统计时间的装饰器为例def timer(func): def inner(*args, **kwargs):...【详细内容】
2021-05-07  Tags: Django  点击:(221)  评论:(0)  加入收藏
在介绍 Django 内置的响应类之前,读者需要了解 HTTP 的响应方式。首先:网站的运行原理是遵从 HTTP 协议,分为 HTTP 请求和 HTTP 响应。HTTP 响应方式也称为 HTTP 状态码,分为5中...【详细内容】
2021-04-20  Tags: Django  点击:(247)  评论:(0)  加入收藏
HTTP的弊端及HTTPS的由来众所周知HTTP协议是以TCP协议为基石诞生的一个用于传输Web内容的一个网络协议,在"网络分层模型"中属于"应用层协议"的一种.那么在这里我们并不研究...【详细内容】
2021-04-01  Tags: Django  点击:(250)  评论:(0)  加入收藏
Django框架是PythonWeb三大主流框架之一,以其功能强大全面而受到众多开发者追捧,现如今Django已经更新到3版本,但是并不推荐使用,更多建议使用1版本。Django版本Python版本1.112...【详细内容】
2020-09-27  Tags: Django  点击:(68)  评论:(0)  加入收藏
▌简易百科推荐
大家好,我是菜鸟哥,今天跟大家一起聊一下Python4的话题! 从2020年的1月1号开始,Python官方正式的停止了对于Python2的维护。Python也正式的进入了Python3的时代。而随着时间的...【详细内容】
2021-12-28  菜鸟学python    Tags:Python4   点击:(1)  评论:(0)  加入收藏
学习Python的初衷是因为它的实践的便捷性,几乎计算机上能完成的各种操作都能在Python上找到解决途径。平时工作需要在线学习。而在线学习的复杂性经常让人抓狂。费时费力且效...【详细内容】
2021-12-28  风度翩翩的Python    Tags:Python   点击:(1)  评论:(0)  加入收藏
Python 是一个很棒的语言。它是世界上发展最快的编程语言之一。它一次又一次地证明了在开发人员职位中和跨行业的数据科学职位中的实用性。整个 Python 及其库的生态系统使...【详细内容】
2021-12-27  IT资料库    Tags:Python 库   点击:(2)  评论:(0)  加入收藏
菜单驱动程序简介菜单驱动程序是通过显示选项列表从用户那里获取输入并允许用户从选项列表中选择输入的程序。菜单驱动程序的一个简单示例是 ATM(自动取款机)。在交易的情况下...【详细内容】
2021-12-27  子冉爱python    Tags:Python   点击:(4)  评论:(0)  加入收藏
有不少同学学完Python后仍然很难将其灵活运用。我整理15个Python入门的小程序。在实践中应用Python会有事半功倍的效果。01 实现二元二次函数实现数学里的二元二次函数:f(x,...【详细内容】
2021-12-22  程序汪小成    Tags:Python入门   点击:(32)  评论:(0)  加入收藏
Verilog是由一个个module组成的,下面是其中一个module在网表中的样子,我只需要提取module名字、实例化关系。module rst_filter ( ...); 端口声明... wire定义......【详细内容】
2021-12-22  编程啊青    Tags:Verilog   点击:(8)  评论:(0)  加入收藏
运行环境 如何从 MP4 视频中提取帧 将帧变成 GIF 创建 MP4 到 GIF GUI ...【详细内容】
2021-12-22  修道猿    Tags:Python   点击:(6)  评论:(0)  加入收藏
面向对象:Object Oriented Programming,简称OOP,即面向对象程序设计。类(Class)和对象(Object)类是用来描述具有相同属性和方法对象的集合。对象是类的具体实例。比如,学生都有...【详细内容】
2021-12-22  我头秃了    Tags:python   点击:(9)  评论:(0)  加入收藏
所谓内置函数,就是Python提供的, 可以直接拿来直接用的函数,比如大家熟悉的print,range、input等,也有不是很熟,但是很重要的,如enumerate、zip、join等,Python内置的这些函数非常...【详细内容】
2021-12-21  程序员小新ds    Tags:python初   点击:(5)  评论:(0)  加入收藏
Hi,大家好。我们在接口自动化测试项目中,有时候需要一些加密。今天给大伙介绍Python实现各种 加密 ,接口加解密再也不愁。目录一、项目加解密需求分析六、Python加密库PyCrypto...【详细内容】
2021-12-21  Python可乐    Tags:Python   点击:(8)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条