Reputation: 3968
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?
Upvotes: 7
Views: 3754
Reputation: 3439
Python 3, Django==2.1.7
def add_user_to_group(sender, instance: User, created: bool, **kwargs):
try:
if created:
group = Group.objects.get(name=instance.user_type)
instance.groups.add(group)
instance.save()
except Group.DoesNotExist:
pass
models.signals.post_save.connect(add_user_to_group, sender=User)
Upvotes: 3
Reputation: 6675
In my case I was trying to map the is_staff
attribute to a group called "staff". Thanks to @RemcoGerlich's answer I was finally able to come up with something that worked for me:
@receiver(post_save, sender=User)
def save_user_person(sender, instance, **kwargs):
user = instance
instance.person.save()
group = Group.objects.get(name='staff')
if user.is_staff and not user.groups.filter(name='staff').exists():
user.groups.add(group)
elif not user.is_staff and user.groups.filter(name='staff').exists():
user.groups.remove(group)
@receiver(m2m_changed, sender=User.groups.through)
def sync_staff_to_group(instance, action, **kwargs):
user = instance
if action == 'post_remove' or action == 'post_add' or action == 'post_clear':
group = Group.objects.get(name='staff')
if user.is_staff and not user.groups.filter(name='staff').exists():
user.groups.add(group)
elif not user.is_staff and user.groups.filter(name='staff').exists():
user.groups.remove(group)
Upvotes: 0
Reputation: 31270
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:
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
.
Upvotes: 3