Django中间件Middleware详解:原理、配置与实战案例

Mason
Mason
发布时间:2026-10-12| 6人浏览过
原创

本文深入解析Django中间件Middleware的工作原理、配置方法及执行顺序。通过MIDDLEWARE_CLASSES设置中间件,详解process_request与process_response的执行流程。提供流量统计、异常处理、移动端识别及本地化等实用中间件代码示例,帮助开发者掌握全局请求处理技巧。

中间件介绍

中间件(Middleware)位于请求(request)与响应(response)处理之间,属于轻量级的全局处理层,用于修改Django的输入与输出。由于其影响全局,使用时需谨慎,不当使用可能影响系统性能。

每个中间件通常负责特定功能,例如 负责会话(sessions)处理。

激活中间件

需在 settings.py 配置文件中配置 MIDDLEWARE_CLASSES 列表。

MIDDLEWARE_CLASSES = [
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

若无需使用任何中间件,可将该列表设为空。

中间件顺序

浏览器发出的请求(Request)经Django处理后返回响应(HttpResponse),其传递过程涉及 process_request 和 process_response 的执行,两者顺序相反,具体流程如图所示:

每个请求首先经过中间件的 process_request 函数,该函数返回 None 或 HttpResponse 对象。若返回 None,则继续处理后续中间件;若返回 HttpResponse 对象,则中断处理并直接返回给网页。中间件无需继承特定类(可继承 object),其基本结构如下:

class CommonMiddleware(object):
 def process_request(self, request):
 return None

 def process_response(self, request, response):
 return response

中间件涉及以下几个关键钩子(hook):

  • process_request()
  • process_exception()(仅当视图抛出异常时调用)
  • process_template_response()
  • process_response()

常用的内置中间件组件包括:

1. Sessions(会话处理)

2. Authentication(身份认证)

3. CSRF Protection(跨站请求伪造保护)

4. GZipping Content(内容压缩)

例如,若需实现流量统计功能:

class BlockedIpMiddleware(object):
 def process_request(self, request):
   ...数据库拿access值
   access = access+1
   ...存起来,类似这个原理  

上述代码实现简单的访问计数累加,需将该中间件的Python路径写入 settings.py 中。

MIDDLEWARE_CLASSES = (
 'zjj.middleware.BlockedIpMiddleware',
 ...其它的中间件
)

Django 会按照 MIDDLEWARE_CLASSES 中从上到下的顺序依次执行各中间件的 process_request 函数,而 process_response 函数的执行顺序则与注册顺序相反,即最前面的中间件最后执行。

二、在服务器正式运行后,通常将 DEBUG 设置为 False 以提升安全性,但这会导致错误详情页面无法显示。如何同时兼顾安全与错误调试?

普通访问者看到的是友好的错误提示信息。

管理员则可以看到详细的错误信息,以便修复BUG。

利用中间件可以实现这一需求,代码如下:

import sys
from django.views.debug import technical_500_response
from django.conf import settings

class UserBasedExceptionMiddleware(object):
 def process_exception(self, request, exception):
  if request.user.is_superuser or request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
   return technical_500_response(request, *sys.exc_info())

将该中间件添加到 settings.py 的 MIDDLEWARE_CLASSES 中,建议置于列表末尾,以便观察其他中间件的 process_request 错误。

当访问者为管理员时,系统会返回错误详情,例如访问不存在的页面时。

普通用户看到的是标准的 404 错误页面,而管理员则能看到详细报错信息。

三、分享一个识别移动设备的中间件,更详细的实现可参考 django-mobi 项目。

MOBILE_USERAGENTS = ("2.0 MMP","240x320","400X240","AvantGo","BlackBerry",
 "Blazer","Cellphone","Danger","DoCoMo","Elaine/3.0","EudoraWeb",
 "Googlebot-Mobile","hiptop","IEMobile","KYOCERA/WX310K","LG/U990",
 "MIDP-2.","MMEF20","MOT-V","NetFront","Newt","Nintendo Wii","Nitro",
 "Nokia","Opera Mini","Palm","PlayStation Portable","portalmmm","Proxinet",
 "ProxiNet","SHARP-TQ-GX10","SHG-i900","Small","SonyEricsson","Symbian OS",
 "SymbianOS","TS21i-10","UP.Browser","UP.Link","webOS","Windows CE",
 "WinWAP","YahooSeeker/M1A1-R2D2","iPhone","iPod","Android",
 "BlackBerry9530","LG-TU915 Obigo","LGE VX","webOS","Nokia5800")

class MobileTemplate(object):
 """
 If a mobile user agent is detected, inspect the default args for the view 
 func, and if a template name is found assume it is the template arg and 
 attempt to load a mobile template based on the original template name.
 """

 def process_view(self, request, view_func, view_args, view_kwargs):
  if any(ua for ua in MOBILE_USERAGENTS if ua in 
   request.META["HTTP_USER_AGENT"]):
   template = view_kwargs.get("template")
   if template is None:
    for default in view_func.func_defaults:
     if str(default).endswith(".html"):
      template = default
   if template is not None:
    template = template.rsplit(".html", 1)[0] + ".mobile.html"
    try:
     get_template(template)
    except TemplateDoesNotExist:
     pass
    else:
     view_kwargs["template"] = template
     return view_func(request, *view_args, **view_kwargs)
  return None

再举一个本地化(Localization)中间件的例子:

class LocaleMiddleware(object):

 def process_request(self, request):

  if 'locale' in request.cookies:
   request.locale = request.cookies.locale
  else:
   request.locale = None

 def process_response(self, request, response):

  if getattr(request, 'locale', False):
   response.cookies['locale'] = request.locale

该中间件将 cookies 中的 locale 值赋给 request 中的 locale 属性,供后续视图使用。

本部分参考了 Django 官方文档及网络教程,感谢各位前辈的分享。

总结

以上就是本文的全部内容,希望本文对您的学习或工作有所帮助。如有疑问欢迎留言交流,感谢支持。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。