且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-10-23 12:09:34

我认为这与此有关:问题嘛nyToMany关系不保存后立即更新。有些地方在评论中报告说,它仍然是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而不是instance.is_superuser:
如果不是instance.groups.filter(name ='staff_user')。exists():
try:
g = Group.objects.get(name = 'staff_user')
除了Group.DoesNotExist:
pass
else:
instance.groups.add(g)

这是假设信号接收的是一个用户的实例,否则看起来有点不同。检查操作和检查组是否已经添加是为了防止无限循环。发件人是许多关系的隐藏的通过表, User.groups.through


Hello, I'm using Django 1.9. Trying to add a user to group on creation or save. Using either user.groups or groups.user_set.add don't work, mix and match with pre- and post-save below.

These answers aren't working for me, and so this isn't a dupe: Adding user to group on creation in Django
Adding a user to a group in django
Add users to groups in Django

I have tried both methods in both pre- and post-save handlers.

@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()

You can mix and match which method is used where, I have tried it. I don't use more than one method in testing. After hitting the save button on user admin page, the user is not shown as in the group.

I double-checked that the handlers are getting called, user logic is correct, etc.

Is there something I'm doing wrong, or something that has changed in 1.9 to break the old methods?

Thanks!

Edit: For those asking, the group is created like this:

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

permissions = Permission.objects.all()
for p in permissions:
    group.permissions.add(p)
group.save()

I have debugged it and the group definitely exists, though maybe I made it wrong and so it won't be applied?

I think it's related to this: Issue with ManyToMany Relationships not updating inmediatly after save . Somethere reports in a comment that it's still current in 1.10.

The problem is that you can also select groups on the admin 'add user' page; and then when you save the User, the following happens:

  1. The User is saved
  2. The post-save signal happens, and you add the User to the group
  3. All groups of the User are cleared
  4. The groups that were chosen on the add user page are added to the User.

You can use a m2m_changed signal, apparently. I've never used it, but I think something like this should work:

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)

This is assuming the instance that the signal receives is a User, otherwise it's going to look slightly different. The check for the action and the check whether the group was already added are to prevent infinite loops. The sender is the hidden 'through' table for the many to many relation, User.groups.through.