From e3a3a414073a726c5d5ae39fc0ab71211276b1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E6=AC=A3=E6=80=A1?= <3093609022@qq.com> Date: Sun, 9 Nov 2025 21:39:32 +0800 Subject: [PATCH] =?UTF-8?q?yxy=E6=B7=BB=E5=8A=A0=20middleware.py=20?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DjangoBlog-master/blog/middleware.py | 66 ++++++++++++++++--- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/middleware.py b/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/middleware.py index 94dd70c9..6e496e1a 100644 --- a/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/middleware.py +++ b/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/middleware.py @@ -1,42 +1,90 @@ +# 导入日志模块,用于记录中间件运行过程中的日志信息 import logging +# 导入时间模块,用于计算页面渲染耗时 import time +# 从ipware工具导入获取客户端IP的函数 from ipware import get_client_ip +# 从user_agents工具导入解析用户代理的函数 from user_agents import parse +# 导入博客相关的ES配置和文档管理器(用于记录页面加载时间) from blog.documents import ELASTICSEARCH_ENABLED, ElaspedTimeDocumentManager +# 创建当前模块的日志记录器 logger = logging.getLogger(__name__) class OnlineMiddleware(object): + """ + 自定义Django中间件,用于: + 1. 计算页面渲染耗时 + 2. 收集客户端信息(IP、用户代理) + 3. 在启用Elasticsearch时记录访问性能数据 + 4. 替换响应中的特定标记为实际加载时间 + """ + def __init__(self, get_response=None): + """ + 中间件初始化方法 + :param get_response: Django框架传入的处理响应的函数,用于链式调用中间件 + """ self.get_response = get_response + # 调用父类初始化方法(Python 2兼容写法,在Python 3中可省略) super().__init__() def __call__(self, request): - ''' page render time ''' + """ + 中间件核心处理方法,在请求到达视图前和响应返回客户端前执行 + :param request: Django的请求对象,包含客户端请求信息 + :return: 处理后的响应对象 + """ + # 记录请求处理开始时间(用于计算耗时) start_time = time.time() + + # 调用下一个中间件或视图函数,获取响应对象 response = self.get_response(request) + + # 从请求头中获取用户代理字符串(如浏览器型号、系统等信息) http_user_agent = request.META.get('HTTP_USER_AGENT', '') + # 获取客户端IP地址(第二个返回值为是否是公开IP,此处暂不使用) ip, _ = get_client_ip(request) + # 解析用户代理字符串,转换为可操作的对象(方便提取浏览器、系统等信息) user_agent = parse(http_user_agent) + + # 判断响应是否为非流式响应(流式响应无法修改内容,如文件下载) if not response.streaming: try: + # 计算页面渲染总耗时(当前时间 - 开始时间) cast_time = time.time() - start_time + + # 如果启用了Elasticsearch,记录性能数据 if ELASTICSEARCH_ENABLED: + # 将耗时转换为毫秒并保留2位小数 time_taken = round((cast_time) * 1000, 2) + # 获取当前请求的URL路径 url = request.path + # 导入Django的时区工具,用于记录当前时间 from django.utils import timezone + # 通过文档管理器向Elasticsearch插入一条性能记录 ElaspedTimeDocumentManager.create( - url=url, - time_taken=time_taken, - log_datetime=timezone.now(), - useragent=user_agent, - ip=ip) + url=url, # 访问的URL + time_taken=time_taken, # 页面加载耗时(毫秒) + log_datetime=timezone.now(), # 记录时间(当前时区) + useragent=user_agent, # 解析后的用户代理信息 + ip=ip # 客户端IP地址 + ) + + # 将响应内容中的标记替换为实际耗时(保留前5位字符) + # 注:需确保响应内容为bytes类型,因此使用str.encode转换 response.content = response.content.replace( - b'', str.encode(str(cast_time)[:5])) + b'', str.encode(str(cast_time)[:5]) + ) + + # 捕获所有异常,避免中间件错误导致请求失败 except Exception as e: - logger.error("Error OnlineMiddleware: %s" % e) + # 记录异常信息到日志 + logger.error("Error in OnlineMiddleware: %s" % e) - return response + # 返回处理后的响应对象 + return response \ No newline at end of file