优化大版本
This commit is contained in:
@@ -235,8 +235,43 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
||||
'EditBonusChange': '编辑变更',
|
||||
'DeleteBonusChange': '删除变更',
|
||||
'OperationLogView': '操作日志查询',
|
||||
'LawyersdocumentsDetail': '文件详情', # 确保映射正确
|
||||
'BulletinDetail': '公告详情', # 确保映射正确
|
||||
'ScheduleDetail': '日程详情', # 确保映射正确
|
||||
# 添加路径变体的映射
|
||||
'Bulletindetail': '公告详情', # bulletindetail 路径
|
||||
'Scheduledetail': '日程详情', # scheduledetail 路径
|
||||
'Lawyersdocumentsdetail': '文件详情', # lawdisplay 路径对应的类
|
||||
}
|
||||
return name_mapping.get(class_name, None)
|
||||
# 先尝试直接匹配
|
||||
result = name_mapping.get(class_name, None)
|
||||
if result:
|
||||
return result
|
||||
|
||||
# 如果直接匹配失败,尝试不区分大小写匹配
|
||||
for key, value in name_mapping.items():
|
||||
if key.lower() == class_name.lower():
|
||||
return value
|
||||
|
||||
return None
|
||||
|
||||
def path_to_class_name(self, path):
|
||||
"""从URL路径推断可能的类名"""
|
||||
# 移除前导斜杠并分割路径
|
||||
parts = path.strip('/').split('/')
|
||||
if not parts or not parts[-1]:
|
||||
return None
|
||||
|
||||
# 获取最后一部分(通常是视图名称)
|
||||
last_part = parts[-1]
|
||||
|
||||
# 将下划线或连字符分隔的名称转换为驼峰命名
|
||||
# 例如: bulletindetail -> BulletinDetail
|
||||
words = last_part.replace('-', '_').split('_')
|
||||
class_name = ''.join(word.capitalize() for word in words)
|
||||
|
||||
# 返回转换后的类名(即使不是标准驼峰命名也返回,让调用者尝试匹配)
|
||||
return class_name if class_name else None
|
||||
|
||||
def func_name_to_description(self, func_name):
|
||||
"""从函数名转换为中文描述"""
|
||||
@@ -278,6 +313,7 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
||||
return response
|
||||
|
||||
# 正常请求,记录详细日志
|
||||
description = None
|
||||
try:
|
||||
# 解析URL获取view函数
|
||||
resolver_match = resolve(request.path)
|
||||
@@ -285,8 +321,6 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
||||
view_class = getattr(view_func, 'view_class', None)
|
||||
|
||||
# 获取接口描述
|
||||
description = None
|
||||
|
||||
if view_class:
|
||||
# 优先从对应方法的docstring获取(针对APIView)
|
||||
method = request.method.lower()
|
||||
@@ -316,29 +350,46 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
||||
func_name = view_func.__name__
|
||||
description = self.func_name_to_description(func_name)
|
||||
|
||||
# 如果还是没有找到描述,使用默认值
|
||||
if not description:
|
||||
description = '未知接口'
|
||||
|
||||
# 记录日志,格式与Django默认格式保持一致,并在最后添加接口描述
|
||||
timestamp = datetime.now().strftime('[%d/%b/%Y %H:%M:%S]')
|
||||
log_message = f'{timestamp} "{request.method} {request.path} HTTP/1.1" {response.status_code} {description}'
|
||||
|
||||
# 使用print输出到控制台(与Django开发服务器日志格式保持一致)
|
||||
print(log_message)
|
||||
|
||||
except Resolver404:
|
||||
# URL无法解析
|
||||
# 如果是未授权请求,可能是恶意扫描,只记录简要信息
|
||||
if is_unauthorized:
|
||||
timestamp = datetime.now().strftime('[%d/%b/%Y %H:%M:%S]')
|
||||
print(f'{timestamp} [未授权访问] "{request.method} {request.path}" {response.status_code}')
|
||||
else:
|
||||
timestamp = datetime.now().strftime('[%d/%b/%Y %H:%M:%S]')
|
||||
print(f'{timestamp} "{request.method} {request.path} HTTP/1.1" {response.status_code} 未知接口')
|
||||
except Exception:
|
||||
# 发生异常时不影响请求处理,使用默认格式
|
||||
timestamp = datetime.now().strftime('[%d/%b/%Y %H:%M:%S]')
|
||||
print(f'{timestamp} "{request.method} {request.path} HTTP/1.1" {response.status_code} 未知接口')
|
||||
# URL无法解析,尝试从路径推断
|
||||
possible_class_name = self.path_to_class_name(request.path)
|
||||
if possible_class_name:
|
||||
description = self.class_name_to_description(possible_class_name)
|
||||
# 如果直接匹配失败,尝试匹配常见的变体
|
||||
if not description and possible_class_name:
|
||||
# 尝试匹配:Bulletindetail -> BulletinDetail
|
||||
if possible_class_name.lower().endswith('detail'):
|
||||
# 将 detail 前的部分首字母大写
|
||||
base = possible_class_name[:-6] # 移除 'detail'
|
||||
if base:
|
||||
# 尝试匹配:Bulletin + Detail
|
||||
variant = base.capitalize() + 'Detail'
|
||||
description = self.class_name_to_description(variant)
|
||||
except Exception as e:
|
||||
# 发生异常时,尝试从路径推断
|
||||
try:
|
||||
possible_class_name = self.path_to_class_name(request.path)
|
||||
if possible_class_name:
|
||||
description = self.class_name_to_description(possible_class_name)
|
||||
# 如果直接匹配失败,尝试匹配常见的变体
|
||||
if not description and possible_class_name:
|
||||
if possible_class_name.lower().endswith('detail'):
|
||||
base = possible_class_name[:-6]
|
||||
if base:
|
||||
variant = base.capitalize() + 'Detail'
|
||||
description = self.class_name_to_description(variant)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 如果还是没有找到描述,使用默认值
|
||||
if not description:
|
||||
description = '未知接口'
|
||||
|
||||
# 记录日志,格式与Django默认格式保持一致,并在最后添加接口描述
|
||||
timestamp = datetime.now().strftime('[%d/%b/%Y %H:%M:%S]')
|
||||
log_message = f'{timestamp} "{request.method} {request.path} HTTP/1.1" {response.status_code} {description}'
|
||||
|
||||
# 使用print输出到控制台(与Django开发服务器日志格式保持一致)
|
||||
print(log_message)
|
||||
|
||||
return response
|
||||
|
||||
Reference in New Issue
Block a user