Django添加signals信号记录操作日志

发布时间 2023-08-17 18:24:32作者: lytcreate
models.py

class OperationLog(models.Model):
    model_name = models.CharField(max_length=100)
    operation = models.CharField(max_length=100)
    object_id = models.PositiveIntegerField()
    created_at = models.DateTimeField(auto_now_add=True)
    account = models.CharField(max_length=100, default='anonymous')

    def __str__(self):
        return f"{self.model_name} - {self.operation} - ID: {self.object_id}"


from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
@receiver(post_save)
def create_operation_log(sender, instance=None, created=False, **kwargs):
    if sender == OperationLog:
        # 避免记录操作日志时出现循环调用
        return

    if created:
        operation = 'create'
    else:
        operation = 'update'
    # 解决报错 AttributeError: 'Migration' object has no attribute 'account'
    if 'makemigrations' not in sys.argv and 'migrate' not in sys.argv:
        OperationLog.objects.create(
            model_name=sender._meta.model_name,
            operation=operation,
            object_id=instance.id,
            account=instance.account
        )

@receiver(post_delete)
def delete_operation_log(sender, instance=None, **kwargs):
    if sender == OperationLog:
        # 避免记录操作日志时出现循环调用
        return
    # 解决报错 AttributeError: 'Migration' object has no attribute 'account'
    if 'makemigrations' not in sys.argv and 'migrate' not in sys.argv:
        OperationLog.objects.create(
            model_name=sender._meta.model_name,
            operation='delete',
            object_id=instance.id,
            account=instance.account
        )

 

其他表的字段默认包含id,如果需要记录其他字段,比如account,即操作人,那么需要每个表都有account字段就可以,比如这种:

class ImageUpload(models.Model):
    sid = models.CharField(max_length=64, default=uuid.uuid4().hex)  # ID
    image = models.ImageField(upload_to='xxx/', default='xxx/default.png')  # 文件
    account = models.CharField(max_length=50, default='admin')  # 更新用户
    update_time = models.DateTimeField(auto_now=True)  # 更新时间