详解Django中间件执行顺序

yipeiwu_com5年前Python基础

中间件

Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性。

我们可以使用中间件,在Django处理视图的不同阶段对输入或输出进行干预。

1 中间件的定义方法

定义一个中间件工厂函数,然后返回一个可以别调用的中间件。

中间件工厂函数需要接收一个可以调用的get_response对象。

返回的中间件也是一个可以被调用的对象,并且像视图一样需要接收一个request对象参数,返回一个response对象。

def simple_middleware(get_response):
 # 此处编写的代码仅在Django第一次配置和初始化的时候执行一次。

 def middleware(request):
  # 此处编写的代码会在每个请求处理视图前被调用。

  response = get_response(request)

  # 此处编写的代码会在每个请求处理视图之后被调用。

  return response

 return middleware

例如,在users应用中新建一个middleware.py文件,

def my_middleware(get_response):
 print('init 被调用')
 def middleware(request):
  print('before request 被调用')
  response = get_response(request)
  print('after response 被调用')
  return response
 return middleware

定义好中间件后,需要在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',
 'users.middleware.my_middleware', # 添加中间件
]

定义一个视图进行测试

def demo_view(request):
 print('view 视图被调用')
 return HttpResponse('OK')

执行结果

注意:Django运行在调试模式下,中间件init部分有可能被调用两次。

2 执行流程

3 多个中间件的执行顺序

  • 在请求视图被处理前,中间件由上至下依次执行
  • 在请求视图被处理后,中间件由下至上依次执行

示例:

定义两个中间件

def my_middleware(get_response):
 print('init 被调用')
 def middleware(request):
  print('before request 被调用')
  response = get_response(request)
  print('after response 被调用')
  return response
 return middleware

def my_middleware2(get_response):
 print('init2 被调用')
 def middleware(request):
  print('before request 2 被调用')
  response = get_response(request)
  print('after response 2 被调用')
  return response
 return middleware

注册添加两个中间件

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',
 'users.middleware.my_middleware', # 添加
 'users.middleware.my_middleware2', # 添加
]

执行结果

init2 被调用
init 被调用
before request 被调用
before request 2 被调用
view 视图被调用
after response 2 被调用
after response 被调用

总结:中间件的本质其实就是个装饰器,对于装饰器我之前的随笔里也详细说过,装饰器的本质其实就是个闭包

对于装饰器来说,在这里程序从上到下执行,开始记录装饰器1-3,然后读到了函数的时候,装饰器开始装饰,把函数的引用传入装饰器中,从装饰器3开始往上装饰,所以这时候开始执行装饰器3的初始化,并把装饰完的函数当做一个新的函数,再次把新的引用传入到装饰器2,接着装饰器2进行初始化,再次把新的函数的引用传入到装饰器1进行装饰,这时候装饰器1的初始化开始,并开始执行,从而接下来的执行顺序为1-3执行装饰的内容,最后再执行本来的函数,达到一个对原有函数增加功能和特性的要求。

装饰器:从程序开始的顺序,从上到下读取----》从下到上装饰----》从上到下执行

在中间件中,执行顺序等同,只不过中间件装饰的是视图函数或者是试图类,会有一个init()初始化,为了便于理解我在说明装饰器顺序的时候,那里说的初始化就是现在的init(),也就是中间件在执行上也是从最接近函数或者类的中间件开始初始化,在中间件注册时,如果有多个中间件,程序按照从上到下的顺序来确认中间件,接着执行视图函数的时候,开始从下到上的进行init(),这里的初始化init()类似于Flask框架里四种请求勾子中的请求开始前执行一次的意思,从下到上执行完init后,再从上到下执行请求前所要执行的代码,请求完成后再从下往上执行请求后的代码。

中间件:从程序开始的顺序,从上到下读取----》从下到上初始化init()----》从上到下执行请求前----》视图的请求----》从下到上执行请求后

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持【听图阁-专注于Python设计】。

相关文章

Python CSV文件模块的使用案例分析

Python CSV文件模块的使用案例分析

本文实例讲述了Python CSV文件模块的使用。分享给大家供大家参考,具体如下: 1、CSV模块使用流程 1、导入模块 impport CSV 2、打开文件(xxx.csv)...

node.js获取参数的常用方法(总结)

1、req.body 2、req.query 3、req.params 一、req.body例子 body不是nodejs默认提供的,你需要载入body-parser中间件才可以使用re...

在Django的模型和公用函数中使用惰性翻译对象

在模型和公用函数中,使用ugettext_lazy()和ungettext_lazy()来标记字符串是很普遍的操作。 当你在你的代码中其它地方使用这些对象时,你应当确定你不会意外地转换它...

Python实现读取文件最后n行的方法

本文实例讲述了Python实现读取文件最后n行的方法。分享给大家供大家参考,具体如下: # -*- coding:utf8-*- import os import time impo...

Python单体模式的几种常见实现方法详解

本文实例讲述了Python单体模式的几种常见实现方法。分享给大家供大家参考,具体如下: 这里python实现的单体模式,参考了:https://stackoverflow.com/que...