当前位置:   article > 正文

Django 中间件简介_django process_request

django process_request

1. Django 中间件简介

官方解释称中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局
范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。但是由于其影响的是全局,所以需要谨慎使用
使用不当会影响性能。
  • 1
  • 2
  • 3
简单来说中间件是在视图函数执行之前和执行之后做的一些额外操作,它本质上就是一个自定义类,类中定义了几个方法,
Django框架会在请求的特定的时间去执行这些方法,结构如下所示。
  • 1
  • 2

在这里插入图片描述
Django 自带中间件

在Django中自带7个中间件,如下示例

	# 内置的安全机制,保护用户与网站的通信安全。
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 开启CSRF防护功能
    'django.middleware.csrf.CsrfViewMiddleware',
    # 开启内置的用户认证系统
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # 开启内置的信息提示功能
    'django.contrib.messages.middleware.MessageMiddleware',
    # 防止恶意程序点击劫持
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

查看自带中间件的源码可以发现它们是类,并且很多都带有 process_request 、process_response等方法,并且都继承了MiddlewareMixin类

2. Django 自定义中间件

Django给我们提供了创建自定义中间件的方式,通过创建自定义中间件来实现全局的功能,例如用户黑名单校验、用户访问频率校验、网站全局用户身份校验等等。

Django 提供了5个方法可以用来创建自定义中间件,如下示例

		process_request(self,request)
		process_view(self, request, view_func, view_args, view_kwargs)
		process_template_response(self,request,response)
		process_exception(self, request, exception)
		process_response(self, request, response)


主要使用的是process_request和process_response方法
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

创建自定义中间件的流程

1.创建一个任意名称的文件夹例如 middleware
2.在该文件夹内创建一个任意名称的py文件例如
3.在该py文件内编写中间件类
4.在settings配置文件中注册
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
在这里插入图片描述

process_request

其作用是请求来的时候会从上往下依次执行配置文件中已注册的中间件里面的process_request方法,如果没有则直接跳过。

1. process_request有一个参数,就是request,这个request和视图函数中的request是一样的(在交给Django后面的
路由之前,对这个request对象可以进行一系列的操作)2. 由于request对象是一样的,所以我们可以对request对象进行一系列的操作,包括request.变量名=变量值,这样的操
作,我们可以在后续的视图函数中通过相同的方式即可获取到我们在中间件中设置的值。

3. 它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理
如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

使用示例

from django.utils.deprecation import MiddlewareMixin

class MyMdd1(MiddlewareMixin):
    def process_request(self, request):
        print('这是第一个自定义中间件的内容')

class MyMdd2(MiddlewareMixin):
    def process_request(self, request):
        print('这是第二个自定义中间件的内容')


然后执行一个视图函数,会发现process_request方法里的内容会自动打印,并且按照从上到下的顺序执行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述
在这里插入图片描述

'''注意点'''

在process_request方法中返回一个HttpResponse对象的话,用户请求不会继续往下执行,也就是被拦截了,并返回
process_request方法中的HttpResponse对象内容,也就是说,在第一个自定义中间件process_request方法中拦截后
不会执行下一个自定义中间件的process_request方法,如下示例
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
在这里插入图片描述
总结

中间件的process_request方法是在执行视图函数之前执行的。
当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的。
不同中间件之间传递的request都是同一个对象
  • 1
  • 2
  • 3

process_response

响应走的时候会按照配置文件中注册的中间件从下往上的顺序依次执行每一个中间件里面的process_response方法,该方法必须要有两个形参,并且需要将形参response返回(response是视图函数的返回值),如果内部定义了返回了HttpResponse对象,会将返回给用户浏览器的内容替换成HttpResponse对象

使用示例

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse, redirect


class MyMdd1(MiddlewareMixin):
    def process_request(self, request):
        print('这是第一个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第一个自定义中间件的process_response内容')
        return responce


class MyMdd2(MiddlewareMixin):
    def process_request(self, request):
        print('这是第二个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第二个自定义中间件的process_response内容')
        return responce

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在这里插入图片描述
在这里插入图片描述

'''注意点'''
1. process_response方法有俩个形参,为request、response。其中response是必须要返回的,因为其是视图函数的
返回值
2. 如下不返回response,而返回HttpResponse对象,那么原本视图函数的返回值就被替换了

	from django.utils.deprecation import MiddlewareMixin
	from django.shortcuts import render, HttpResponse, redirect
	
	
	class MyMdd1(MiddlewareMixin):
	    def process_request(self, request):
	        print('这是第一个自定义中间件的process_request内容')
	
	    def process_response(self, request, responce):
	        print('这是第一个自定义中间件的process_response内容')
	        return responce
	
	
	class MyMdd2(MiddlewareMixin):
	    def process_request(self, request):
	        print('这是第二个自定义中间件的process_request内容')
	
	    def process_response(self, request, responce):
	        print('这是第二个自定义中间件的process_response内容')
	        return HttpResponse('又被掉包了')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在这里插入图片描述

process_request、process_response 注意点:
	
	如果process_request返回了HttpResponse对象,那么会从当前位置从下往上执行每一个process_response
	如下图所示

  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

process_view

process_view(self, request, view_func, view_args, view_kwargs)

该方法有四个参数

request 		HttpRequest对象。
view_func 		Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
view_args 		将传递给视图的位置参数的列表.
view_kwargs 	将传递给视图的关键字参数的字典。view_args和view_kwargs都不包含参数(request)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
Django会在路由匹配成功后调用视图函数之前调用process_view方法。

它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的
process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,那么将不会执行Django的视图函数
而是直接在中间件中掉头,倒叙执行一个个process_response方法,最后返回给浏览器
  • 1
  • 2
  • 3
  • 4
  • 5

使用示例

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse, redirect


class MyMdd1(MiddlewareMixin):
    def process_request(self, request):
        print('这是第一个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第一个自定义中间件的process_response内容')
        return responce

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是第一个自定义中间件的process_view内容")
        print(view_func, view_func.__name__)


class MyMdd2(MiddlewareMixin):
    def process_request(self, request):
        print('这是第二个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第二个自定义中间件的process_response内容')
        return responce

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是第二个自定义中间件的process_view内容")
        print(view_func, view_func.__name__)



打印结果
		这是第一个自定义中间件的process_request内容
		这是第二个自定义中间件的process_request内容
		这是第一个自定义中间件的process_view内容
		<function Index at 0x000001481E7B6620> Index
		这是第二个自定义中间件的process_view内容
		<function Index at 0x000001481E7B6620> Index
		这是第二个自定义中间件的process_response内容
		这是第一个自定义中间件的process_response内容
		
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

在这里插入图片描述

'''注意点'''
如果process_view返回了HttpResponse对象,其流程大致如下图所示
  • 1
  • 2

在这里插入图片描述

process_template_response

process_template_response(self,request,response)

该方法有两个参数,一个HttpRequest对象,response是emplateResponse对象
  • 1
  • 2
  • 3
该方法在视图函数执行完成后,且返回的对象中必须要有render属性对应的render方法时触发,顺序是倒序
  • 1

使用示例

视图函数

class Index(View):
    def get(self, request):
        def render():
            return HttpResponse('我是index里面的render函数')

        obj = HttpResponse('index')
        obj.render = render
        return obj
        # return render(request, 'index.html', locals())

    def post(self, request):
        return render(request, 'index.html', locals())
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
自定义中间件


from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse, redirect


class MyMdd1(MiddlewareMixin):
    def process_request(self, request):
        print('这是第一个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第一个自定义中间件的process_response内容')
        return responce

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是第一个自定义中间件的process_view内容")

    def process_template_response(self, request, response):
        print("这是第一个自定义中间件的process_template_response")
        return response


class MyMdd2(MiddlewareMixin):
    def process_request(self, request):
        print('这是第二个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第二个自定义中间件的process_response内容')
        return responce

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是第二个自定义中间件的process_view内容")

    def process_template_response(self, request, response):
        print("这是第二个自定义中间件的process_template_response")
        return response

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
打印结果

这是第一个自定义中间件的process_request内容
这是第二个自定义中间件的process_request内容
这是第一个自定义中间件的process_view内容
这是第二个自定义中间件的process_view内容
这是第二个自定义中间件的process_template_response
这是第一个自定义中间件的process_template_response
这是第二个自定义中间件的process_response内容
这是第一个自定义中间件的process_response内容
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

process_exception

process_exception(self, request, exception)

该方法有两个参数
一个是HttpRequest对象
一个exception是视图函数异常产生的Exception对象
  • 1
  • 2
  • 3
  • 4
  • 5
这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。
如果返回HttpResponse对象,Django将调用中间件中的process_response方法,并返回给浏览器
如果返回None,则交给下一个中间件的process_exception方法来处理异常。执行顺序按照中间件注册顺序的倒序执行。
  • 1
  • 2
  • 3

使用示例

视图函数

class Index(View):
    def get(self, request):
        def render():
            return HttpResponse('我是index里面的render函数')

        obj = HttpResponse('index')
        obj.render = render
        # 抛出异常
        raise ValueError("hh")
        return obj
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
自定义中间件

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse, redirect


class MyMdd1(MiddlewareMixin):
    def process_request(self, request):
        print('这是第一个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第一个自定义中间件的process_response内容')
        return responce

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是第一个自定义中间件的process_view内容")

    def process_template_response(self, request, response):
        print("这是第一个自定义中间件的process_template_response")
        return response

    def process_exception(self, request, exception):
        print('exception', exception)
        print('这是第一个中间件里面的process_exception')


class MyMdd2(MiddlewareMixin):
    def process_request(self, request):
        print('这是第二个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第二个自定义中间件的process_response内容')
        return responce

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是第二个自定义中间件的process_view内容")

    def process_template_response(self, request, response):
        print("这是第二个自定义中间件的process_template_response")
        return response

    def process_exception(self, request, exception):
        print('exception', exception)
        print('这是第二个中间件里面的process_exception')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
打印结果


这是第一个自定义中间件的process_request内容
这是第二个自定义中间件的process_request内容
这是第一个自定义中间件的process_view内容
这是第二个自定义中间件的process_view内容
exception hh
这是第二个中间件里面的process_exception
exception hh
这是第一个中间件里面的process_exception
这是第二个自定义中间件的process_response内容
这是第一个自定义中间件的process_response内容
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

给 MyMdd2 添加返回值

class MyMdd2(MiddlewareMixin):
    def process_request(self, request):
        print('这是第二个自定义中间件的process_request内容')

    def process_response(self, request, responce):
        print('这是第二个自定义中间件的process_response内容')
        return responce

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是第二个自定义中间件的process_view内容")

    def process_template_response(self, request, response):
        print("这是第二个自定义中间件的process_template_response")
        return response

    def process_exception(self, request, exception):
        print('exception', exception)
        print('这是第二个中间件里面的process_exception')
        return HttpResponse(str(exception))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
打印结果

这是第一个自定义中间件的process_request内容
这是第二个自定义中间件的process_request内容
这是第一个自定义中间件的process_view内容
这是第二个自定义中间件的process_view内容
exception hh
这是第二个中间件里面的process_exception
这是第二个自定义中间件的process_response内容
这是第一个自定义中间件的process_response内容
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在第二个中间件中process_exception添加HttpResponse返回值后,不会执行第一个中间件的process_exception方法。

流程图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/71710
推荐阅读
相关标签
  

闽ICP备14008679号