如何在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
相关产品推荐
相关产品推荐

