Django框架admin管理页面中,记录每个字段数据修改变更,特定字段变更执行特定动作

应用背景:

近期在做一个小应用,使用的是Django框架,其中有一个需求是要对数据中每个字段的修改、变更进行记录。

为什么要这么做?主要应用的场景是对于不分表单有“审核”流程,审核结果有通过、不通过;即使对于通过的数据, 后续的审核流程中,仍然有更改审核结果的权限,因此必须记录每个人对每个字段的修改内容,便于做追溯。

具体做法:

针对这个需求,在网上也查了很多资料,但是好像都没有比较完善系统的说法,于是看着Django官方文档,结合众多网友的的方案做尝试。主要步骤:

  1. 初步选定重写 save_model 函数来实现保存的时候做好记录;
  2. 新建一个model,用于记录数据变更结果;(应用MySql数据库)
  3. 在save_model中获取表单数据;
  4. 再保存表单时,将数据写入表单。

相关代码:

虽然可以使用日志作为数据记录,但是日志一般是文本格式,结构性不强,不便于后期的查询处理。所以还是选择使用数据库进行记录;同时日志也使用了;(至于速度嘛……都用python了,还考虑啥访问速度……)

数据记录表:

# models.py
# 简单日志记录,用于主要记录节点信息
class RzLog(models.Model):
    guid = models.UUIDField(auto_created=True, default=uuid.uuid4, editable=False)
    sheet = models.CharField('表单名称', max_length=100, default='')
    user = models.CharField('操作人员', max_length=100, default='')
    the_id = models.CharField('数据ID', max_length=255, default='')
    the_key = models.CharField('字段名称', max_length=255, default='')
    old_values = models.CharField('原数据', max_length=255, default='')
    new_values = models.CharField('新数据', max_length=255, default='')
    log_date = models.DateTimeField('修改时间', default=choice_list.date_time, null=True)  
    note = models.TextField('备注信息', null=True, default='', blank=True)
    create_user = models.ForeignKey(User,  related_name='create_user_rz', on_delete=models.CASCADE, db_constraint=False, verbose_name='创建人员', default=1000)
    update_user = models.ForeignKey(User, related_name='update_user_rz', on_delete=models.CASCADE, db_constraint=False, verbose_name='修改人员', default=1000)
    create_date = models.DateTimeField('创建时间', auto_now_add=True)
    update_date = models.DateTimeField('更新时间', auto_now=True)

admin中重写save_model 代码,其中通过form.has_changed()来获取变更字段的数据。以下是相关代码,代码中使用了大量的日志记录,这个是初期调试的时候,一步步尝试的时候应用的,后期正式应用可以去掉,为了让大家能更清晰地应用,这里先保留了所以记录和说明。

# admin.py
def save_model(self, request, obj, form, change):
    obj.update_user = request.user
    obj.receiver = request.user.username

    # 用于记录数据变化信息
    if form.has_changed():
        change_list = form.changed_data  
        logger.info(f'表格数据变化点:{change_list}')
        try:
            changed_dict = form.cleaned_data
            
            for i in change_list:
                x = YiJieShou.objects.values_list(i, flat=True).filter(id=obj.id)  # 原数据库保存的数据
                y = changed_dict[i] # 当前新写入的数据
                # ----------------------------------
                # 如果有特殊字段需要另外的动作进行处理的,使用下面的部分代码

                # 当变更审批状态的时候
                if i == 'is_jieshou':  # 此处为特别关注的字段,针对此字段的变动如果需要有其他的操作,可以在此处进行设置相关动作
                    obj.jieshou_date = datetime.datetime.now()
                    if not y:
                        pass # 设定特殊动作
                    else:
                        pass
                elif i == 'is_doubt':
                    if y == 1:
                        pass # 设定特殊动作
                    else:
                        pass # 设定特殊动作
                else:
                     pass # 设定特殊动作
                # ---------------------------------------------------------
                # 如果不需要特殊字段的处理,跳过 -- 之间的不分代码即可

    # 将相关数据的变化,写入数据库进行存储
 RzLog.objects.create(sheet='PassJieShou',user=request.user.username,the_id=str(obj),the_key=i,old_values=str(x[0]),new_values=str(y),log_date=datetime.datetime.now(),create_user=request.user)

        except  BaseException as e:        
            logger.error(f'错误类型是:{e.__class__.__name__}\n错误原因: {e}')
            logger.error(f'详细错误信息a:{traceback.format_exc()}')
    super().save_model(request, obj, form, change)

上面代码中的x 、y分别代表的是,x原来表单中保存的数据, y本次新写入的{修改的)数据;

如果只需要简单的记录数据的变化,可以直接由x\y,直接跳转RzLog.objects.create()部分。中间部分是针对一些特殊字段,设定特殊的动作用的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值