1.中间件的应用场景
例如:可以使用中间件对请求做出拦截,限制用户(可以从HttpRequest中拿到客户端的IP地址)的访问频率,例如1分钟内不允许访问10次。很显然,这需要在访问视图函数之前对用户做校验,因此可以利用process_request函数完成。
考虑这样一种场景:视图返回JSON数据(对于Web开发,这很常见),但是由于需求的不同,因此数据结构很难统一。此时,可以利用中间件对响应对象再做一层包装,统一数据结构,可以利用process_response函数完成。
2.中间件的钩子函数
process_request🧨
在处理视图函数之前(准确地说,是在完成通过URL找到视图函数之前),Django会调用这个钩子函数。之后,根据函数返回值的不同会有不同的效果
process_view🍟
图预处理函数。首先,来看该函数的定义:
def process_view(self, request, view_func, view_args, view_kwargs):
这个钩子函数同样会在视图函数之前执行,但是与process_request不同的是,它会在确定了当前请求对应的视图函数之后被调用:
request:HttpRequest对象实例。
view_func:解析当前请求得到的视图函数,它是一个实际的函数对象。
view_args:传递给视图函数的位置参数,它是一个元组对象。
view_kwargs:传递给视图函数的关键字参数,它是一个字典对象。
process_exception🛺
def process_exception(self, request, exception):
当视图函数抛出了未捕获的异常时,这个钩子函数会被调用。它接受两个参数,含义分别如下:
request:HttpRequest对象实例。
exception:视图函数抛出的异常对象。
该函数主要用来对异常信息做一些记录和对异常的修复,如视图函数抛出异常之后,给用户展示友好的错误提示信息
process_template_response🎶
即TemplateResponse或响应实例有render方法的后处理函数,定义如下:
def process_template_response(self, request, response):
它会在视图函数执行之后被调用,且需要保证返回的响应对象包含可调用的render方
法。接受两个参数,含义如下:
request:HttpRequest对象实例。
response:TemplateResponse或存在render方法的对象,可以是视图函数或中间件返回的。
process_response🙌
即响应后处理函数,它的定义如下:
def process_response(self, request, response):
这个函数的调用时机是Django执行了视图函数并生成响应之后。它接受两个参数,含义如下:
request:HttpRequest对象实例。
response:视图或中间件返回的响应对象。
3.自定义中间件
定义中间件最直接的方法是继承自django.utils.deprecation.MiddlewareMixin,并选择实现适合的钩子函数
通常会将中间件定义在middleware.py文件中
from django.utils.deprecation import MiddlewareMixin class FirstMiddleware(MiddlewareMixin): def process_request(self, request): print("要想过此路,留下买路钱!")
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', # 加入此行,post是应用名 'post.middleware.FirstMiddleware', ]
此时访问任意路径,会先进行中间件逻辑的管控:
[13/Oct/2022 21:24:15] "GET /post/watch/ HTTP/1.1" 200 153 要想过此路,留下买路钱!