Django框架的添加自定义中间件 定制常用功能为中间件配置

首页 » Python教程 » Django框架的添加自定义中间件 定制常用功能为中间件配置

如果你知道了csrf是什么的话,中间件也非常简单。就是说我们发送POST请求,会首先经过csrf进行判断是否存在效验的token,没有就报错,那么我们来看一下csrf在settings.py配置文件中的内容:

from django.middleware.csrf import CsrfViewMiddleware
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就知道这里面就是一些django默认的中间件了,现在如果我们想要自定义中间件的话,按照通常的套路就是照个葫芦画个瓢而已。其实这里面都是一些类,我们呢看一下如何这些类如何定义的,我们自己定义一个就好了。还是导入一下查看一下源代码发现,每一个类都是继承MiddlewareMixin,再往下看就是下面的代码:

class MiddlewareMixin:
    def __init__(self, get_response=None):
        self.get_response = get_response
        super().__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        response = response or self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response

process_request方法

现在我们已经知道了中间件里面可以定义process_request和process_response这两个方法,并且需要在settings.py的中间件中注册自己定义的类的路径,那么现在我在django工程目录下创建一个middle文件夹,在里面创建一个m1.py文件用来定义中间件:

from django.utils.deprecation import MiddlewareMixin
class Mple1(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------1号')


class Mple2(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------2号')

class Mple3(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------3号')

然后需要在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',
    'middle.m1.Mple1',
    'middle.m1.Mple2',
    'middle.m1.Mple3',
]

这里可以重新定义一个URL路由规则:http://127.0.0.1:8000/test/,在视图views.py中创建test函数:

def test(request):
    print('鳄鱼君Ba------终结者')
    return HttpResponse('ok')
运行django程序,访问:http://127.0.0.1:8000/test/,会在页面显示ok,会在控制台打印:

鳄鱼君Ba-------1号
鳄鱼君Ba-------2号
鳄鱼君Ba-------3号
鳄鱼君Ba------终结者
[26/Apr/2020 10:54:27] "GET /test/ HTTP/1.1" 200 2

process_response方法

那么现在来总结一下,发送一个get请求,会先经历中间件所有的process_request方法。我们再来看一下process_response方法,这里只需要修改mi.py文件,其它的地方不需要修改:

from django.utils.deprecation import MiddlewareMixin

class Mple1(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------1号')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------6')
        return response
class Mple2(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------2号')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------5')
        return response
class Mple3(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------3号')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------4')
        return response

运行程序则会在控制台打印以下信息:

鳄鱼君Ba-------1号
鳄鱼君Ba-------2号
鳄鱼君Ba-------3号
鳄鱼君Ba------终结者
鳄鱼君Ba------------4
鳄鱼君Ba------------5
鳄鱼君Ba------------6
[26/Apr/2020 10:52:55] "GET /test/ HTTP/1.1" 200 2

按照控制台输出的信息,get请求会先经过所有中间件的process_request方法,然后到views.py函数的test函数,最后经过process_response方法。为什么在process_response方法中需要设置返回值呢,你可以注释掉6号的返回值,或者全部process_response方法的返回值,就会报错:AttributeError: ‘NoneType’ object has no attribute ‘get’

我们再来说一下process_request和process_response方法中的request和response参数是什么。request跟viewsy.py视图中test函数的request参数一样,都包含了用户请求的所有信息。所有的请求过来会首先经过中间件的process_request方法,那么我们可以在这里判断一下请求是否携带请求头,如果没有就终止掉。现在你可以修改1号位置的process_request方法,让它直接返回“滚”,那么现在再发送请求就会显示让你滚!

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class Mple1(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------1号')
        return HttpResponse('滚')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------6')
        return response
class Mple2(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------2号')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------5')
        return response
class Mple3(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------3号')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------4')
        return response

运行程序则会在控制台打印以下信息:

鳄鱼君Ba-------1号
鳄鱼君Ba------------6
[26/Apr/2020 10:59:35] "GET /test/ HTTP/1.1" 200 3

这里可以看到在1号位置直接让请求滚蛋,那么就会执行process_response方法,然后结束。在中间中中还有一些其它的方法,我们再来简单了解一下。

process_view方法

在你的每一个类中添加这个方法:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class Mple1(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------1号')
    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        print('鳄鱼君Ba----------------view终结者1')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------6')
        return response
class Mple2(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------2号')
    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        print('鳄鱼君Ba----------------view终结者2')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------5')
        return response
class Mple3(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------3号')
    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        print('鳄鱼君Ba----------------view终结者3')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------4')
        return response

运行程序则会在控制台打印以下信息:

鳄鱼君Ba-------1号
鳄鱼君Ba-------2号
鳄鱼君Ba-------3号
鳄鱼君Ba----------------view终结者1
鳄鱼君Ba----------------view终结者2
鳄鱼君Ba----------------view终结者3
鳄鱼君Ba------终结者
鳄鱼君Ba------------4
鳄鱼君Ba------------5
鳄鱼君Ba------------6
[26/Apr/2020 11:11:30] "GET /test/ HTTP/1.1" 200 2

那么现在又发现,现在请求的周期变为:process_request方法—>process_view方法—>views.py视图的test方法—->process_response方法。process_view方法中的request, view_func, view_func_args, view_func_kwargs参数跟views.py视图test方法的参数一样,为了接收不同个数的参数。

process_exception

process_exception方法是用来做异常处理的,我们呢可以在3号位置添加一个process_exception方法,在views.py视图函数中出现错误的时候它才会执行,需要记住这一点。那么修改test让它出错,这个应该很简单吧。这里的exception就是异常的信息,你可以可以打印一下,一般我们可以这样使用:

class Mple3(MiddlewareMixin):
    def process_request(self,request):
        print('鳄鱼君Ba-------3号')
    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        print('鳄鱼君Ba----------------view终结者3')
    def process_exception(self,request,exception):
        print(exception)  #打印错误,查看类型
        if isinstance(exception,ValueError):  #判断一下错误是否是exception的子类
            return HttpResponse('出错了')
    def process_response(self,request,response):
        print('鳄鱼君Ba------------4')
        return response

如果在views.py视图的函数出错,那么就会返回错误信息,当然前提是你知道错误的信息是什么。

process_template_response

默认情况下不执行,如果视图views.py函数返回的对象中,存在render方法就会执行。

class Aoo():
    def render(self):
        return HttpResponse('ok')
def test(request):
    print('鳄鱼君Ba------终结者')
    return Aoo()
def process_template_response(self,request,response):
    print('-----------------------------')
    return response

如果想继续执行就必须返回response,否则就会报错:ValueError: Mple3.process_template_response didn’t return an HttpResponse object. It returned None instead.
,没什么用,你自己玩吧!

每个方法的参数都是固定的,尽量不要随意更改。到现在你应该知道,一个请求会经历哪些部分了吧,放一张图片加深印象:

Django框架的添加自定义中间件 定制常用功能为中间件配置

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《Django框架的添加自定义中间件 定制常用功能为中间件配置》 发布于2020-04-26

分享到:
赞(0) 赏杯咖啡

评论 抢沙发

5 + 4 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册