Django使用signals自动添加用户到分组时groups.add方法不生效
问题根因
User和Group是多对多关联关系,关联数据存在独立的中间表中,多对多的add()操作要求关联的两个模型实例都已经完成数据库写入、持有合法主键,才能在中间表写入关联记录。
你当前使用的是pre_save信号,信号触发时User实例还未真正提交到数据库,没有生成对应主键,此时执行instance.groups.add(group)无法在中间表落库,自然不生效。
而last_name是User表自身的普通字段,你在pre_save阶段给实例的该属性赋值,等后续模型执行save操作时会直接把属性值写入User表对应列,所以可以正常生效。
可行解决方案
方案1:替换为post_save信号(适用于非Django Admin新建用户的场景)
将信号从pre_save改为post_save,这个信号触发时User实例已经完成数据库写入,持有合法主键,可以正常操作多对多关系。注意加created判断,仅在用户首次创建时执行分组添加逻辑,避免每次更新用户信息都重复执行操作:
from django.db.models.signals import post_save from django.dispatch import receiver from django.contrib.auth.models import User, Group @receiver(post_save, sender=User) def add_to_pro_group(sender, instance, created, **kwargs): if created: pro_group = Group.objects.get(name='Pro') instance.groups.add(pro_group) instance.last_name = 'some name' print('user has been group : ' + pro_group.name)
方案2:适配Django Admin场景的处理
如果你是在Django Admin后台新增用户,上面的post_save方法可能还是不生效,原因是Admin的保存逻辑会在主表post_save触发后,再单独处理表单提交的groups、用户权限这类多对多字段,会把信号里添加的分组覆盖掉,这种场景可以选择以下两种处理方式:
- 重写对应UserAdmin的
save_model方法,在多对多关系保存完成后再执行分组添加逻辑 - 监听
m2m_changed信号,当User和Group的关联表发生变更时,检查目标用户是否属于Pro分组,不存在则补加关联关系
内容的提问来源于stack exchange,提问作者Antoine Grenard
相关产品推荐
相关产品推荐

