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

如何在Django save_model中获取旧字段值以管理项目负责人权限

解决Django Admin中获取旧Project负责人以移除权限的问题

要解决移除旧负责人lead_project权限的问题,核心是拿到修改前的原始Project对象——当前的obj是已经被表单修改后的实例,数据库里还保留着旧数据。下面是具体的实现方案:

方法:在save_model中获取旧对象(推荐)

利用Django Admin传递的change参数(True表示更新现有对象,False表示新建),在更新场景下从数据库取出原始的Project对象,就能拿到旧的负责人了。修改你的save_model方法如下:

class ProjectAdmin(GuardedModelAdmin):
    # 你的其他配置...
    def save_model(self, request, obj, form, change):
        # 仅在更新项目时处理旧权限移除
        if change:
            # 从数据库获取修改前的原始Project对象
            old_project = Project.objects.get(pk=obj.pk)
            old_leader = old_project.projectLeader
            if old_leader:
                # 移除旧负责人的lead_project权限
                remove_perm("lead_project", old_leader, obj)
        
        # 给新负责人分配权限(优化了原代码的查询逻辑)
        new_leader = obj.projectLeader
        if new_leader:
            assign_perm("lead_project", new_leader, obj)
        
        # 最后调用父类方法完成保存,符合Django Admin规范
        super().save_model(request, obj, form, change)

几个关键优化和注意点:

  • 不需要额外查询Project.objects.get(name=obj),因为obj本身就是Project的实例,直接传给assign_perm/remove_perm即可,减少数据库查询开销。
  • 直接使用obj.projectLeader替代get_projectLeaderid()(如果get_projectLeaderid()只是返回projectLeader.id的话),更直观简洁。
  • 增加非空判断:因为projectLeader字段允许blank=True, null=True,避免空对象调用权限方法报错。
  • 调用super().save_model()完成保存,比直接写obj.save()更符合Django Admin的扩展规范。

补充:为什么能拿到旧对象?

当在Admin中修改对象时,obj是已经被表单数据更新后的实例,但此时还没有执行save()操作,所以数据库中存储的仍然是修改前的原始数据。通过obj.pk(主键)查询出来的old_project就是修改前的状态,自然能拿到旧的projectLeader。

内容的提问来源于stack exchange,提问作者Rubick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:24:02