views.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. from django.utils import timezone
  2. from .models import OperationLog
  3. class OperationLogger:
  4. @staticmethod
  5. def log_operation(request, operation_content, operation_level, operator=None,
  6. operation_result='success', module_name=None, object_id=None):
  7. """
  8. 记录操作日志
  9. Args:
  10. request: HttpRequest对象
  11. operation_content: 操作内容描述
  12. operation_level: 操作级别
  13. operator: 操作者标识(用户名等),如果为None则尝试从request中获取
  14. operation_result: 操作结果,'success'或'failure'
  15. module_name: 模块名称,用于分类
  16. object_id: 操作对象ID
  17. """
  18. try:
  19. # 验证必需参数
  20. if not request or not operation_content or not operation_level:
  21. raise ValueError("缺少必需的参数: request, operation_content, operation_level")
  22. # 获取操作者标识
  23. operator_identifier = OperationLogger._get_operator_identifier(request, operator)
  24. # 获取模块名称(如果没有提供则从请求路径推断)
  25. if not module_name:
  26. module_name = OperationLogger._infer_module_name(request.path)
  27. # 获取客户端信息
  28. ip_address = OperationLogger._get_client_ip(request)
  29. user_agent = request.META.get('HTTP_USER_AGENT', '')[:500] # 限制长度
  30. # 创建日志记录
  31. OperationLog.objects.create(
  32. operator=operator_identifier,
  33. operation_content=operation_content,
  34. operation_level=operation_level,
  35. operation_result=operation_result,
  36. ip_address=ip_address,
  37. user_agent=user_agent,
  38. request_method=request.method,
  39. request_path=request.path,
  40. module_name=module_name,
  41. object_id=object_id
  42. )
  43. except Exception as e:
  44. # 日志记录失败不应影响主要业务逻辑,但需要记录错误
  45. import logging
  46. logger = logging.getLogger(__name__)
  47. logger.error(f"操作日志记录失败: {str(e)}", exc_info=True)
  48. @staticmethod
  49. def _get_operator_identifier(request, operator):
  50. """获取操作者标识"""
  51. # 如果提供了operator参数,直接使用
  52. if operator is not None:
  53. return str(operator)
  54. # 尝试从request中获取用户信息
  55. if hasattr(request, 'user') and request.user.is_authenticated:
  56. # 优先使用username,如果没有则使用其他标识
  57. if hasattr(request.user, 'username'):
  58. return request.user.username
  59. elif hasattr(request.user, 'get_username'):
  60. return request.user.get_username()
  61. else:
  62. return f"用户ID:{request.user.id}" if hasattr(request.user, 'id') else "认证用户"
  63. # 如果都没有,返回未知用户
  64. return "未知用户"
  65. @staticmethod
  66. def _infer_module_name(path):
  67. """从路径推断模块名称"""
  68. if not path:
  69. return 'unknown'
  70. # 移除首尾斜杠并分割路径
  71. path_parts = path.strip('/').split('/')
  72. if path_parts:
  73. # 使用第一个非空路径部分作为模块名
  74. for part in path_parts:
  75. if part and part not in ('api', 'v1', 'v2'): # 跳过常见的API前缀
  76. return part
  77. return 'unknown'
  78. @staticmethod
  79. def _get_client_ip(request):
  80. """获取客户端IP地址"""
  81. x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
  82. if x_forwarded_for:
  83. ip = x_forwarded_for.split(',')[0].strip()
  84. else:
  85. ip = request.META.get('REMOTE_ADDR')
  86. return ip
  87. # 快捷函数
  88. def log_operation(request, operation_content, operation_level, operator=None,
  89. operation_result='success', module_name=None, object_id=None):
  90. """快捷记录操作日志函数"""
  91. OperationLogger.log_operation(
  92. request=request,
  93. operation_content=operation_content,
  94. operation_level=operation_level,
  95. operator=operator,
  96. operation_result=operation_result,
  97. module_name=module_name,
  98. object_id=object_id
  99. )
  100. # 专门用于成功操作的快捷函数
  101. def log_success_operation(request, operation_content, operation_level, operator=None,
  102. module_name=None, object_id=None):
  103. """记录成功操作的快捷函数"""
  104. log_operation(
  105. request=request,
  106. operation_content=operation_content,
  107. operation_level=operation_level,
  108. operator=operator,
  109. operation_result='success',
  110. module_name=module_name,
  111. object_id=object_id
  112. )
  113. # 专门用于失败操作的快捷函数
  114. def log_failure_operation(request, operation_content, operation_level, operator=None,
  115. module_name=None, object_id=None):
  116. """记录失败操作的快捷函数"""
  117. log_operation(
  118. request=request,
  119. operation_content=operation_content,
  120. operation_level=operation_level,
  121. operator=operator,
  122. operation_result='failure',
  123. module_name=module_name,
  124. object_id=object_id
  125. )