如何在Django中为数据库日志添加自定义字段存储额外信息?
解决Django操作日志存储额外字段的问题
方案一:扩展django-db-logger实现自定义字段
1. 自定义日志模型
在项目app的models.py中创建继承自django_db_logger的模型,添加所需额外字段:
from django.db import models from django_db_logger.models import DatabaseLog class CustomDatabaseLog(DatabaseLog): username = models.CharField(max_length=255, blank=True, null=True) request_url = models.CharField(max_length=500, blank=True, null=True) # 可根据需求添加更多字段,如用户ID、客户端IP、操作类型等 class Meta: verbose_name = "自定义操作日志" verbose_name_plural = "自定义操作日志"
2. 自定义日志Handler
在app中创建handlers.py,重写默认Handler的emit方法以保存自定义字段:
import logging from django_db_logger.db_log_handler import DatabaseLogHandler from .models import CustomDatabaseLog class CustomDatabaseLogHandler(DatabaseLogHandler): def emit(self, record): try: extra = record.__dict__.get('extra', {}) log_entry = CustomDatabaseLog( level=record.levelname, message=record.getMessage(), module=record.module, process=record.process, thread=record.thread, username=extra.get('username'), request_url=extra.get('request_url'), # 映射其他自定义字段 ) log_entry.save() except Exception: self.handleError(record)
3. 修改settings.py的LOGGING配置
替换默认handler为自定义实现:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(asctime)s %(message)s' }, }, 'handlers': { 'db_log': { 'level': 'DEBUG', # 替换为自定义handler的完整路径 'class': 'your_app.handlers.CustomDatabaseLogHandler' }, }, 'loggers': { 'db': { 'handlers': ['db_log'], 'level': 'DEBUG' }, 'django.request': { 'handlers': ['db_log'], 'level': 'ERROR', 'propagate': False, } } }
4. 在代码中传递额外参数
日志调用时通过extra参数传入自定义信息:
import logging db_logger = logging.getLogger('db') @api_view(['POST']) def user(request): # 获取当前用户名(未登录则取请求体中的用户名或标记为匿名) current_username = request.user.username if request.user.is_authenticated else request.data.get('username', '匿名用户') db_logger.info( "进入注册API", extra={ 'username': current_username, 'request_url': request.path } ) if request.method == "POST": body = json.loads(request.body.decode('utf-8')) body['password'] = hash_sha256(body['password']) duplicate = Profile.objects.filter(username=body['username']) if len(duplicate) != 0: db_logger.critical( "用户名重复", extra={ 'username': body['username'], 'request_url': request.path } ) return Response({"message": "نام کاربری تکراری است."}, status=status.HTTP_409_CONFLICT) instance = Profile.objects.create(**body) db_logger.info( f'用户{instance.username}创建成功', extra={ 'username': instance.username, 'request_url': request.path } ) return Response({"username": body['username']})
5. 迁移数据库
执行命令创建新的日志表:
python manage.py makemigrations python manage.py migrate
方案二:完全自定义日志系统
若扩展第三方库不够灵活,可从零实现日志功能:
1. 创建日志模型
from django.db import models from django.utils import timezone class OperationLog(models.Model): LEVEL_CHOICES = ( ('DEBUG', 'DEBUG'), ('INFO', 'INFO'), ('WARNING', 'WARNING'), ('ERROR', 'ERROR'), ('CRITICAL', 'CRITICAL'), ) level = models.CharField(max_length=20, choices=LEVEL_CHOICES) message = models.TextField() username = models.CharField(max_length=255, blank=True, null=True) request_url = models.CharField(max_length=500, blank=True, null=True) module = models.CharField(max_length=100) created_at = models.DateTimeField(default=timezone.now) class Meta: ordering = ['-created_at'] verbose_name = "操作日志" verbose_name_plural = "操作日志"
2. 自定义日志Handler
import logging from .models import OperationLog class OperationLogHandler(logging.Handler): def emit(self, record): try: extra = record.__dict__.get('extra', {}) log_entry = OperationLog( level=record.levelname, message=record.getMessage(), username=extra.get('username'), request_url=extra.get('request_url'), module=record.module, ) log_entry.save() except Exception: self.handleError(record)
3. 配置与使用
参考方案一修改LOGGING配置,在代码中通过extra传递自定义参数即可。
方案三:使用审计日志专用库
若需跟踪模型变更+用户行为,可使用审计日志库(如django-auditlog):
基本使用
- 安装后在
INSTALLED_APPS中添加:
INSTALLED_APPS = [ # ... 'auditlog', ]
- 为模型注册审计跟踪:
from auditlog.registry import auditlog from .models import Profile auditlog.register(Profile)
- 手动记录自定义操作:
from auditlog.models import LogEntry from django.contrib.contenttypes.models import ContentType # 记录用户注册完成操作 LogEntry.objects.log_action( user_id=request.user.id, content_type_id=ContentType.objects.get_for_model(Profile).pk, object_id=instance.id, object_repr=str(instance), action_flag=LogEntry.ACTION_FLAG_VIEW, change_message="用户完成注册操作", )
内容的提问来源于stack exchange,提问作者Aylin Naebzadeh
相关产品推荐
相关产品推荐

