You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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):

基本使用

  1. 安装后在INSTALLED_APPS中添加:
INSTALLED_APPS = [
    # ...
    'auditlog',
]
  1. 为模型注册审计跟踪:
from auditlog.registry import auditlog
from .models import Profile

auditlog.register(Profile)
  1. 手动记录自定义操作:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 14:30:54