django 自定义中间件
概述
中间件是 Django 请求/响应处理的框架,用于全局改变 Django 的请求输入或响应输出。在请求阶段,在调用视图之前,Django 按照定义settings.MIDDLEWARE
的顺序应用中间件 MIDDLEWARE,自顶向下。
第一种自定义中间件
中间件的结构:
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return respons
def process_view(request, view_func, view_args, view_kwargs)
return None or HttpResponse(xx)
def process_exception(self, request, exception):
return None or HttpResponse(xx)
def process_template_response(self, request, response)
return
__init__
方法在服务器启动时被调用,用于中间件的初始化。__call__
方法在每次请求时被调用,可以在此处添加自定义逻辑
示例1:
1、第一步:自定义日志中间件,在myapp文件下创建一个middleware.py文件,在文件内定义LoggingMiddleware 中间件类
# 对Request请求与视图响应返回做日志记录
# myapp.middleware.LoggingMiddleware
import logging
class LoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
logging.info(f'Request: {request.method} {request.path}')
response = self.get_response(request)
logging.info(f'Response: {response.status_code}')
return response
2、在settings.py中注册中间件,即可。
MIDDLEWARE = [
# ...
'myapp.middleware.LoggingMiddleware',
# ...
]
第二种自定义中间件
示例2:
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class SimpleMiddleware(MiddlewareMixin):
def process_request(self, request):
# 执行路由之前被调用,返回None就是通过,返回HttpResponse 就是拦截成功
print("收到请求,但还没执行 url 路由")
return None
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
# 调用视图函数之前被调用,返回None就是通过,返回HttpResponse 就是拦截成功
print("以运行了url指向, 但还没开始执行视图")
return None
def process_exception(self, request, exception):
# 视图里面出错了,就会自动到这个里面执行,返回HttpResponse
# 抓异常,发日志/邮件
print("视图执行出错了")
return None
def process_response(self, request, response):
# 所有的响应返回给浏览器之前被调用,返回HttpResponse
# 一定会走这个逻辑,即使view里面代码错了,先走错的,再走这个
print("视图执行出错了")
return None
# def process_template_response(self, request, response):
# # 很少用
# # 只有我们的视图里面返回了render渲染的,才会走这个
# print("视图返回了render函数")
# return None
process_request(self, request)
1、process_view()
只在 Django 执行url前被调用。
2、例举场景:在process_request()
中我们可以定义合适的 限流或权限啥的
process_view(self, request, view_func, view_func_args, view_func_kwargs)
1、process_view()
只在 Django 调用视图前被调用。
2、它只能返回 None 或 HttpResponse 对象。如果它返回 None,Django 将继续处理这个请求,执行任何其他的 process_view()
,然后执行相应的视图(request里的url指向的视图)。如果返回 HttpResponse 对象,Django不会去影响调用相应的视图;它会将响应中间件应用到 HttpResponse 并返回结果。
3、例举场景:在process_view()
中我们可以定义合适的 权限验证啥的
process_exception(self, request, exception)
1、在视图执行期间,出现异常而被抛出时,就会执行该方法。
2、当视图引发异常时,Django 会调用 process_exception()
。process_exception()
应该返回 None 或 HttpResponse 对象。如果它返回一个 HttpResponse 对象,模板响应和响应中间件将被应用且会将结果响应返回浏览器。否则,就会开始默认异常处理
3、例举场景:process_exception()
可以用来定义规范异常的错误输出和响应请求
process_response(self, request, response)
1、所有的响应返回给浏览器之前被调用,返回HttpResponse,一定会走这个逻辑,即使view里面代码错了,先走错的process_exception()
,再走这个
2、例举场景:用于规范响应输出格式啥的
process_template_response(self, request, response)
1、request 是一个 HttpRequest 对象。response 是 TemplateResponse 对象(或者等效对象),它通过 Django 视图或中间件返回。
2、process_template_response() 在视图被完全执行后调用,且视图返回的是 render() 方法,是一个 TemplateResponse 或等效对象 就会执行到该方法。(因此该方法并不常用)