在 Django 1.9 中保存时将用户添加到组

std*_*ave 5 python django

你好,我使用的是 Django 1.9。尝试在创建或保存时将用户添加到组。使用 user.groups 或 groups.user_set.add 都不起作用,请与下面的 pre-save 和 post-save 混合搭配。

这些答案对我不起作用,所以这不是一个骗局: 在 Django 创建时将用户添加到组将用户
添加到 django 中的组
将用户添加到 Django 中的组

我已经在保存前和保存后处理程序中尝试了这两种方法。

@receiver(pre_save, sender=User)
def user_presave_handler(sender, instance, **kwargs):
    if instance.is_staff and not instance.is_superuser:
        # Grant all permissions
        try:
            instance.groups.add(Group.objects.get(name='staff_user'))
        except Group.DoesNotExist:
            pass

@receiver(post_save, sender=User)
def user_postsave_handler(sender, instance, **kwargs):
    if instance.is_staff and not instance.is_superuser:
        try:
            g = Group.objects.get(name='staff_user')
        except Group.DoesNotExist:
            pass
        else:
            g.user_set.add(instance)
            g.save()
Run Code Online (Sandbox Code Playgroud)

哪里可以混用什么方法,我试过了。我在测试中不使用不止一种方法。点击用户管理页面上的保存按钮后,用户不会显示在组中。

我仔细检查了处理程序是否被调用,用户逻辑是否正确等。

是我做错了什么,还是在 1.9 中改变了一些东西以打破旧方法?

谢谢!

编辑:对于那些询问的人,该组是这样创建的:

group, __ = Group.objects.get_or_create(name='staff_user')

permissions = Permission.objects.all()
for p in permissions:
    group.permissions.add(p)
group.save()
Run Code Online (Sandbox Code Playgroud)

我已经调试了它并且该组肯定存在,尽管可能是我弄错了,所以它不会被应用?

Rem*_*ich 3

我认为这与此有关:Issues with ManyToMany Relations not update inmediat after save。有人在评论中报告说它在 1.10 中仍然有效。

问题是您还可以在管理“添加用户”页面上选择组;然后当您保存用户时,会发生以下情况:

  1. 用户已保存
  2. 发生保存后信号,并且您将用户添加到组中
  3. 用户的所有组都被清除
  4. 在添加用户页面上选择的组将添加到用户中。

显然,您可以使用 m2m_changed 信号。我从未使用过它,但我认为这样的东西应该有效:

from django.db.signals import m2m_changed

@receiver(m2m_changed, sender=User.groups.through)
def user_groups_changed_handler(sender, instance, action, **kwargs):
    if action == 'post_add' and instance.is_staff and not instance.is_superuser:
        if not instance.groups.filter(name='staff_user').exists():
            try:
                g = Group.objects.get(name='staff_user')
            except Group.DoesNotExist:
               pass
            else:
                instance.groups.add(g)
Run Code Online (Sandbox Code Playgroud)

这是假设instance接收到的信号是用户,否则看起来会略有不同。检查操作和检查组是否已添加是为了防止无限循环。发送者是多对多关系的隐藏“直通”表User.groups.through