Django中间件开发

Django中间件开发

中间件是一个轻量的、框架级别的插件系统,用来处理Django的请求和响应,在全局范围内改变Django的输入和输出。中间件本质上就是一个自定义类,负责实现一些特定的功能,类中定义了几个方法,Django会在请求的特定的时间去执行这些方法。

Django中间件基本知识

中间件限定在5个方法内写代码,这5个方法的执行顺序也遵循一定的规则,只有准确把握这两点,才能在中间件的开发工作中大大减少出错概率。

中间件配置

要想使用一个中间件,必须把它添加到配置文件settings中

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',
    'test_middleware.middlewares.middlewaretest1.middle1',
    'test_middleware.middlewares.middlewaretest1.middle2',
]

说明:

没有任何中间件是必须的,在上面的列表可以删除任何中间件,但建议保留CommonMiddleware中间件。

中间件彼此之间可能存在依赖关系,因此列表中的中间件要按照一定顺序排列。

在请求阶段调用视图之前,Django以列表中定义的顺序(自上而下)调用中间件;在处理响应时,调用中间件是倒序,自下而上的。

中间件的方法

  • process_request(self,request)

    参数request是一个HttpRequest对象。

    Django在执行URL配置之前调用process_request()。这个方法返回None或一个HttpResponse对象。如果返回None,Django继续处理请求,程序向下进行;如果返回一个HttpResponse对象,Django不再向下执行程序,直接返回这个对象。

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

    参数request是一个HttpResponse对象;参数view_func是视图函数对象,注意不是视图函数名称的字符串形式;参数view_args是视图函数的位置参数列表;参数view_kwargs是视图函数的关键字参数字典。

    process_view()方法在Django调用视图之前调用,这个方法返回None或一个HttpResponse对象。如果返回None,Django继续处理请求,程序向下进行;如果返回一个HttpResponse对象,Django不再向下执行程序,直接返回这个对象。

  • process_template_response(self,request,response)

    参数response是一个TemplateResponse对象,由Django视图或其他中间件传递过来。

    process_template_response在视图执行完毕后,如果响应实例有render()方法才会被调用。这个方法返回一个实现render()方法的响应对象。因此可以修改传入的response的response.template_name和response,context_data,也可以创建并返回全新的TemplateResponse对象。

    该方法很少用到。

  • process_response(self,request,response)

    参数request是一个HttpResponse对象;参数response是Django视图或中间件传递过来的HttpResponse对象。

    process_response在所有的响应返回给浏览器之前被调用。这个方法返回一个HttpResponse对象。因此可以修改传入的response,或者创建并返回新的HttpResponse对象。

  • process_exception(self,request,exception)

    参数request是一个HttpResponse对象;参数exception是一个Exception对象,由视图函数抛出。

    process_exception在视图函数抛出异常时被调用。这个方法返回None或一个HttpResponse对象。如果返回HttpResponse对象,会经过响应中间件和模板文件渲染,把得到的响应返回给浏览器。否则使用默认的方法处理异常。

中间件执行流程

在请求阶段调用视图之前,Django会按照MIDDLEWARE中定义的顺序,自上而下应用中间件的两个方法。先自上而下执行每个中间件的process_request()方法,然后自上而下执行每个中间件的process_view()方法。

在响应阶段调用视图之后,中间件会按照MIDDLEWARE中定义的顺序相反的顺序自下而上调用中间件的3个方法,正常情况下,一般自下而上执行每一个中间件的process_response()方法;如果视图出错或抛出异常,自下而上执行每一个中间件的process_exception()方法,然后自下而上执行每一个中间件process_response()方法;如果响应实例有render方法,自下而上执行每一个中间件的process_template_response()方法,然后自下而上执行每一个中间件的的process_response()方法。

样例10: Django中间件编程

URL配置

在test_orm项目中建立一个test_middleware应用并加入settings中,在urls中加入path('test_middleware/',include('test_middleware.urls')),

在应用下新建urls文件并写入:

from django.urls import path
from . import  views
urlpatterns = [
    # 一个普通视图函数的配置项
    path('test/',views.test),
    # 能返回包含render方法的对象的视图函数的配置项
    path('test2/',views.test2),
]

视图函数

在views中写入两个视图函数,一个是test普通视图函数,另一个是test_temp()函数,主要返回一个对象,这个对象包含render方法,这样可以触发中间件的process_template_response():

from django.shortcuts import render,HttpResponse

# Create your views here.
def test(request):
    print('test视图函数运行')
    return HttpResponse('hello world!')

class test_temp(object):
    def __init__(self,response):
        self.response=response
    def render(self):
        return self.response

def test2(request):
    print('test2函数运行,主要为了测试processing_template_response中间件是否运行!!')
    resp=HttpResponse('hello world,this is  test2')
    return test_temp(resp)

在/test_orm/test_middleware/下新建文件夹middlewares,然后在这个文件夹新建文件middlewaretest1.py,在这个文件里新建两个中间件:

from django.utils.deprecation import MiddlewareMixin

class middle1(MiddlewareMixin):
    def process_request(self,request):

        print('中间件1的processs_request运行,请求URL是:',request.path_info)
    def process_response(self,request,response):
        print('中间件1的process_response进行响应,状态短语:',response.reason_phrase)
        return response

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print('中间件1的process_view运行')
    def process_exception(self,request,exception):
        print('中间件1的process_exception运行')

    def process_template_response(self, request, response):
        print("中间件1的process_template_response运行")
        return response

class middle2(MiddlewareMixin):
    def process_request(self, request):
        print('中间件2的processs_request运行,请求主机IP:{}端口号:{}'.format(request.META.get('REMOTE_ADDR'),request.META.get('SERVER_PORT')))

    def process_response(self, request, response):
        print('中间件2的process_response进行响应,状态码:',response.status_code)
        return response
    def process_view(self,request,view_func,view_func_args,view_func_kwargs):
        print('中间件2的process_view运行')
    def process_exception(self,request,exception):
        print('中间件2的process_exception运行')
    def process_template_response(self, request, response):
        print("中间件2的process_template_response运行")
        return response

注册自定义中间价

在settings的MIDDLEWARE中加入

'test_middleware.middlewares.middlewaretest1.middle1',
'test_middleware.middlewares.middlewaretest1.middle2',

测试中间件

启动程序,浏览器输入http://127.0.0.1:8000/test_middleware/test/,当网页正确打开后,可以看到命令行终端显示出中间件方法打印出的信息。

中间件1的processs_request运行,请求URL是: /test_middleware/test/
中间件2的processs_request运行,请求主机IP:127.0.0.1端口号:8000
中间件1的process_view运行
中间件2的process_view运行
test视图函数运行
中间件2的process_response进行响应,状态码: 200
中间件1的process_response进行响应,状态短语: OK

我们把视图函数test中的HttpResponse修改成HttpResponse22,故意形成一个错误,再次运行程序:

中间件1的processs_request运行,请求URL是: /test_middleware/test/
中间件2的processs_request运行,请求主机IP:127.0.0.1端口号:8000
中间件1的process_view运行
中间件2的process_view运行
test视图函数运行
中间件2的process_exception运行
中间件1的process_exception运行
中间件2的process_response进行响应,状态码: 500
中间件1的process_response进行响应,状态短语: Internal Server Error

可以看到视图函数运行错误代码,process_exception()开始运行,最后运行process_response()。

浏览器输入http://127.0.0.1:8000/test_middleware/test2/:

中间件1的processs_request运行,请求URL是: /test_middleware/test2/
中间件2的processs_request运行,请求主机IP:127.0.0.1端口号:8000
中间件1的process_view运行
中间件2的process_view运行
test2函数运行,主要为了测试processing_template_response中间件是否运行!!
中间件2的process_template_response运行
中间件1的process_template_response运行
中间件2的process_response进行响应,状态码: 200
中间件1的process_response进行响应,状态短语: OK
posted @ 2021-07-24 11:33  KKKyrie  阅读(90)  评论(0编辑  收藏  举报