django -- 中间件 (一)

简介: django -- 中间件

前戏


在前面我们给index和home页面通过加装饰器的方法来判断是不是登录过,如果没登录就返回登录页面。想想也没有什么问题,但是如果我们的视图函数有几百个呢?难道要给这几百个视图函数都加上装饰器吗?答案当然是否定的。我们可以通过中间件的方式来实现。


什么是中间件


看下官方是怎么解释的:中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。

用大白话说就是在视图函数执行之前和执行之后可以做一些额外的操作,本质上就是一个自定义类,类中定义了几个方法,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',
]

MIDDLEWARE配置项是一个列表,列表中是一个个字符串,这些字符串其实是一个个类,也就是一个个中间件


自定义中间件


中间件可以定义五个方法,分别是

  1. process_request(self,request)
  2. process_view(self,request,view_func,view_args,view_kwargs)
  3. process_template_response(self,request,response)
  4. process_exception(self,request,exception)
  5. process_response(self,request,response)

以上方法的返回值可以是一个None或一个HttpResponse对象,如果是None,则继续按照Django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户,就不执行视图里的函数了


process_request


process_request有一个参数,就是request,这个request和视图函数中的request是一样的,可以使用id(request)查看一下。

我们先来写一个中间件,在app下创建个py文件,里面写如下代码

from django.utils.deprecation import MiddlewareMixin
class Middle1(MiddlewareMixin):  # 需要继承这个类
    def process_request(self, request):
        print(id(request))
        print('这是中间件1中的process_request方法')

这就是我们自定义的中间件了,写好之后,需要在settings.py里的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',
    'appTest01.mymiddleware.Middle1',  # 自定义的中间件
]

然后我们去在视图函数里写个视图,如下

def test(request):
    print(id(request))
    print('我是test视图。。。')
    return HttpResponse('ok')

用浏览器去访问

结果:

74576400
这是中间件1中的process_request方法
74576400
我是test视图。。。

我们可以从上面的结果中得到一下信息

1.process_request的执行时间,在视图函数执行之前执行

2.process_request里的参数request和视图函数里的request是一样的

那如果有两个中间件,他们的执行顺序是什么呢?,在添加一个中间件,在注册的时候,放到上面

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, render, redirect
class Middle1(MiddlewareMixin):  # 需要继承这个类
    def process_request(self, request):
        print(id(request))
        print('这是中间件1中的process_request方法')
        return HttpResponse('middle1')
class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print('这是中间件2中的process_request方法')

然后我们再用浏览器请求test视图,会发现浏览器页面显示了middle1,控制台输出了

这是中间件2中的process_request方法
72082704
这是中间件1中的process_request方法

这是因为中间件的执行顺序是我们在setting.py注册时写的顺序,先执行middle2,在执行middle1,而中间件middle1里有返回一个response,所以Django就不往下执行了

总结:

1.process_request的执行时间,在视图函数执行之前执行

2.process_request里的参数request和视图函数里的request是一样的

3.process_request的执行顺序是按照settings.py里的注册顺序执行的

4.如果中间件的返回值为None,则按照正常的流程走,如果中间件有返回response对象,当前中间件后面的中间件的process_request和process_response方法、视图函数都不执行,执行当前中间的process_response方法以及之前的中间的process_response方法


process_response


process_response有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的HttpResponse对象,该方法的返回值也必须是HttpResponse对象

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, render, redirect
class Middle1(MiddlewareMixin):  # 需要继承这个类
    def process_request(self, request):
        print('这是中间件1中的process_request方法')
    def process_response(self, request, response):
        print('这是中间件1中的process_response方法')
        return response
class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print('这是中间件2中的process_request方法')
    def process_response(self, request, response):
        print('这是中间件2中的process_response方法')
        return response

结果:

这是中间件2中的process_request方法
这是中间件1中的process_request方法
我是test视图。。。
这是中间件1中的process_response方法
这是中间件2中的process_response方法

因为我们中间件的注册是middle2在上面,所以请求来了之后先执行middle2的process_request方法,然后执行middle1的process_request方法,在执行视图函数,视图函数执行完之后在从注册的中间件里从下往上执行,因为middle1在最下面,所以先执行middle1的process_response方法。

我们在middle1里的process_request里加个return,在来看看效果

class Middle1(MiddlewareMixin):
    def process_request(self, request):
        print('这是中间件1中的process_request方法')
        return HttpResponse('middle1')  # 增加这句
    def process_response(self, request, response):
        print('这是中间件1中的process_response方法')
        return response

结果:页面返回了middle1

这是中间件2中的process_request方法
这是中间件1中的process_request方法
这是中间件1中的process_response方法
这是中间件2中的process_response方法

这是因为请求执行middle2中的process_request方法,然后执行middle1里的process_request方法,因为middle1的process_request方法里有return,所以就不执行视图函数,接着按照注册中间件的逆序执行process_response方法

 

那我们把这句放到middle2里的process_request里,在来看看

class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print('这是中间件2中的process_request方法')
        return HttpResponse('middle2')  # 增加这句
    def process_response(self, request, response):
        print('这是中间件2中的process_response方法')
        return response

结果:

这是中间件2中的process_request方法
这是中间件2中的process_response方法

代码解释:请求来了之后,先执行middle2里的process_request方法,因为这里有return,所以就直接执行这里的process_response方法,然后再执行这个中间件上面的process_response方法

总结:

1.process_response在视图函数执行之后执行

2.process_response的参数,request,视图函数中用到的request,response,视图函数中返回的response

3.返回值必须是response对象,不能为None

4.process_response的执行执行顺序是按照注册顺序倒序执行


process_view


process_view有四个参数

request是HttpRequest对象,和之前的是一样的

view_func是Django即将使用的视图函数

view_args是传递给视图函数的位置参数列表

view_kwargs是传递给视图函数的关键字参数

Django会在调用视图函数之前执行process_view方法

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, render, redirect
class Middle1(MiddlewareMixin):  # 需要继承这个类
    def process_request(self, request):
        print('这是中间件1中的process_request方法')
    def process_response(self, request, response):
        print('这是中间件1中的process_response方法')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('这是中间件1中的process_view方法')
class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print('这是中间件2中的process_request方法')
    def process_response(self, request, response):
        print('这是中间件2中的process_response方法')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('这是中间件2中的process_view方法')

结果:

这是中间件2中的process_request方法
这是中间件1中的process_request方法
这是中间件2中的process_view方法
这是中间件1中的process_view方法
我是test视图。。。
这是中间件1中的process_response方法
这是中间件2中的process_response方法

process_view是在process_request方法执行之后,视图函数执行之前执行的,是按照中间件注册顺序从上往下执行的

在process_view加个return来看看

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, render, redirect
class Middle1(MiddlewareMixin):
    def process_request(self, request):
        print('这是中间件1中的process_request方法')
    def process_response(self, request, response):
        print('这是中间件1中的process_response方法')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('这是中间件1中的process_view方法')
class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print('这是中间件2中的process_request方法')
    def process_response(self, request, response):
        print('这是中间件2中的process_response方法')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('这是中间件2中的process_view方法')
        return HttpResponse('view2')  # 增加这句

结果:

这是中间件2中的process_request方法
这是中间件1中的process_request方法
这是中间件2中的process_view方法
这是中间件1中的process_response方法
这是中间件2中的process_response方法

代码解释:

先按照中间件的注册顺序,从上往下执行process_request方法(没有return,有return,直接执行该中间件对应的process_response方法)。然后从上往下执行process_view方法,如果某一个process_view方法里有return,则不执行后面的process_view方法,直接从下往上执行process_response方法

总结:

1.process_view的执行时间,是在process_request之后,以及路由匹配之后,在视图函数之前执行

2.参数:request和之前的一样,view_func要执行的视图函数,view_args视图函数的位置参数,view_kwargs视图函数的关键字参数

3.返回值:None正常走,HttpResponse对象,后面的process_view不执行,直接执行process_response方法(从下往上)

4.执行顺序按照中间件的注册顺序从上往下执行


相关文章
|
5月前
|
中间件 程序员 开发工具
Django实践-08中间件的应用
Django实践-08中间件的应用
Django实践-08中间件的应用
|
6天前
|
存储 监控 中间件
使用Django的中间件可以解决哪些问题
【4月更文挑战第25天】Django中间件用于处理用户认证、CSRF防御、点击劫持防护、请求响应修改、自定义需求、全局处理、异常处理、数据压缩、Session管理、URL重写、限流和CORS支持。它们按顺序执行,提供安全性、灵活性及定制功能,优化Web开发体验。
7 0
|
16天前
|
中间件 API 文件存储
Django的扩展包与中间件:增强应用功能的利器
【4月更文挑战第15天】本文介绍了Django的扩展包和中间件,两者用于增强Django应用功能。扩展包是可重用的应用,提供额外功能,如用户认证和API开发。选择合适的扩展包,通过安装、配置,可轻松集成到项目中。中间件则在请求和响应之间执行操作,如身份验证和权限控制。创建中间件类并添加到settings.py中,实现特定功能。扩展包和中间件常结合使用,以实现更复杂的应用需求,提高开发效率和应用性能。
|
9月前
|
前端开发 中间件 数据安全/隐私保护
【Django】创建用户,中间件,表单组件
【Django】创建用户,中间件,表单组件
48 0
|
9月前
|
XML 中间件 数据格式
Django 高级指南:深入理解和使用类视图和中间件
Django 是一款强大的 Python Web 框架,它提供了一套完整的解决方案,让我们能够用 Python 语言快速开发和部署复杂的 Web 应用。在本文中,我们将会深入研究 Django 中的两个高级特性:类视图(Class-Based Views)和中间件(Middleware)。
|
5月前
|
缓存 中间件 Python
Python Web 开发: 解释 Django 中的中间件是什么,以及如何使用?
Python Web 开发: 解释 Django 中的中间件是什么,以及如何使用?
|
6月前
|
中间件 Python
25 Django高级- 中间件
25 Django高级- 中间件
27 0
|
9月前
|
中间件 Python
|
9月前
|
中间件 开发者 Python
[Python]Django中间件
[Python]Django中间件
|
10月前
|
中间件 开发者 Python
16-Django-基础篇-中间件
16-Django-基础篇-中间件