Django删除超级用户后admin操作日志被删除,如何实现日志不被清除?
Django删除用户时保留后台操作日志的实现方案
Django 内置的管理员操作日志对应
django.contrib.admin.models.LogEntry模型,该模型的user外键默认使用on_delete=models.CASCADE级联删除策略,因此删除用户时所有关联的操作日志会被同步删除,要保留日志只需修改该外键的删除逻辑即可。
方案一:修改外键删除策略为置空(最简实现)
该方案不需要新增字段,修改成本最低:
- 第一步:修改
LogEntry模型的user字段属性
在项目任意已注册的应用的models.py中添加以下代码:
from django.contrib.admin.models import LogEntry from django.db import models # 允许user字段为空 user_field = LogEntry._meta.get_field('user') user_field.null = True # 修改外键删除策略为删除用户时置空 user_field.remote_field.on_delete = models.SET_NULL
- 第二步:生成并执行数据库迁移
运行以下命令生成迁移文件,更新数据库层面的外键约束和字段属性:
python manage.py makemigrations python manage.py migrate
- 第三步:兼容空用户的日志显示
默认后台展示操作用户时如果用户为空会显示异常,添加以下代码修改用户展示逻辑:
from django.contrib.admin.models import LogEntry @property def safe_user_repr(self): return str(self.user) if self.user else "*已删除用户*" LogEntry.user_repr = safe_user_repr
方案二:新增冗余字段保留用户名信息(体验更优)
如果需要保留操作人的用户名而不是仅显示「已删除用户」,可以新增冗余字段存储用户名:
- 第一步:给
LogEntry扩展字段
在已注册应用的models.py中添加代码:
from django.contrib.admin.models import LogEntry from django.db import models from django.db.models.signals import pre_save from django.dispatch import receiver # 新增存储操作人用户名的冗余字段 LogEntry.add_to_class('operator_name', models.CharField(max_length=150, null=True, blank=True)) # 监听LogEntry创建,自动写入用户名 @receiver(pre_save, sender=LogEntry) def save_operator_name(sender, instance, **kwargs): if instance.user and not instance.operator_name: instance.operator_name = instance.user.get_username()
- 第二步:修改外键删除策略
和方案一一样修改user字段的on_delete为models.SET_NULL,同时生成执行迁移 - 第三步:修改日志展示逻辑,优先读取冗余的用户名字段:
@property def safe_user_repr(self): return self.operator_name if self.operator_name else "*已删除用户*" LogEntry.user_repr = safe_user_repr
注意事项
- 不要直接修改Django源码中的
LogEntry定义,否则升级Django版本时你的修改会被覆盖 - 执行迁移前建议先备份数据库,避免数据丢失
- 如果你使用自定义的操作日志模型而非Django自带的
LogEntry,直接修改自定义模型中关联用户的外键on_delete属性即可
内容的提问来源于stack exchange,提问作者Zhoomart
相关产品推荐
相关产品推荐

