如何在Django日志中设置含应用名的文件路径而非绝对路径或纯文件名?
Django日志记录带应用名的文件路径解决方案
问题背景
我们需要在Django项目的日志中记录带应用名的文件路径(例如polls/views.py),但默认的日志格式化选项无法满足需求:
filename仅显示文件名(如views.py),无法区分多应用下的同名文件pathname显示完整绝对路径,过于冗长module仅显示模块名,不符合预期格式
尝试直接在格式字符串中使用{os.path.dirname(pathname)}会触发配置错误:
ValueError: Unable to configure formatter 'verbose'
解决方法
Django日志默认不支持在格式字符串中直接调用Python函数,需要自定义格式化类来处理路径逻辑:
步骤1:创建自定义日志格式化类
在项目中新建工具文件(比如utils/logging.py),编写以下代码:
import os import logging from django.conf import settings class AppRelativePathFormatter(logging.Formatter): def format(self, record): # 基于项目根目录计算文件的相对路径 relative_path = os.path.relpath(record.pathname, settings.BASE_DIR) # 统一用/作为路径分隔符,适配跨平台显示 record.app_filename = relative_path.replace(os.sep, '/') # 调用父类方法完成剩余格式化 return super().format(record)
步骤2:修改settings.py中的LOGGING配置
导入自定义格式化类,替换原有的verbose格式化器配置:
from utils.logging import AppRelativePathFormatter import datetime LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { "()": AppRelativePathFormatter, # 指定使用自定义格式化类 "format": "{levelname}: {message} at {asctime} in {app_filename} {funcName} {lineno} (process={process:d}, thread={thread:d})", "style": "{", }, 'default': { 'format': '%(asctime)s - %(levelname)s - %(module)s - %(lineno)d => %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S' }, }, 'handlers': { 'error_file': { 'class': 'logging.handlers.RotatingFileHandler', 'level': 'DEBUG', 'formatter': 'verbose', 'filename': f'logs/error_{datetime.datetime.today().strftime("%Y-%m-%d")}.log', }, 'info_file': { 'class': 'logging.handlers.RotatingFileHandler', 'level': 'INFO', 'formatter': 'verbose', 'filename': f'logs/info_{datetime.datetime.today().strftime("%Y-%m-%d")}.log', }, 'console': { 'class': 'logging.StreamHandler', 'formatter': 'default', }, }, 'loggers': { 'error_logger': { 'handlers': ['error_file', 'console'], 'level': 'DEBUG', 'propagate': False, }, 'info_logger': { 'handlers': ['info_file', 'console'], 'level': 'INFO', 'propagate': False, }, }, }
原理说明
自定义格式化类通过os.path.relpath获取文件相对于项目根目录的路径,将其添加为日志记录对象的新属性app_filename,之后就可以在格式字符串中直接使用这个属性,实现显示应用名/文件名的需求。
内容的提问来源于stack exchange,提问作者SDido
相关产品推荐
相关产品推荐

