Search code examples
python-3.xdjangodjango-modelsdjango-authenticationdjango-permissions

How add user to a group when update and create a user


I created a bunch of groups fallowing this link: https://stackoverflow.com/questions/22250352/programmatically-create-a-django-group-with-permissions#:~:text I subscribed the User class adding a choice field called "role". Basically, that means what role that user has. That way if a user has the role of "staff" . Thus It'll have permissions of the group staff. The problem is: I can't get django to respond the way I expected. I put a signal after saving that it should add the user to the group according to their role. The program looks like this:

# project/app/model.py

class User(AbstractUser):
    class Roles(models.IntegerChoices):
        SUPER = 0, _('SuperAdmins')
        COMPANY = 1, _('Company')
        UNITY = 2, _('Unity')
        STAFF = 3, _('Staff')

   role: Roles = models.IntegerField(choices=Roles.choices, default=Roles.STAFF, verbose_name=_("Role"))

My signal is like:

GROUPS = ['SuperAdmins', 'Company', 'Unity', 'Staff']
@receiver(post_save, sender=User)
def user(sender: User, instance: User, created: bool, **kwargs) -> None:
    """
    This receiver function will set every staff pages that is created to the group staff.

    :param sender: the model that will trigger this receiver
    :param instance: the instance
    :param created: if it was already created
    :param kwargs:
    :return: None
    """
    if created:
        group = Group.objects.get(name=GROUPS[instance.role])
        instance.groups.add(group)
    else:
        group = Group.objects.get(name=GROUPS[instance.role])
        instance.groups.add(group)
        print("update")

When I go to the admin page and I create a new user, everything works as expected. But when I edit the role of an existing user, it just prints the "update" fron the print function but nothing changes. What am I doing wrong?


Solution

  • I'll post the solution here in case anyone encounters the same problem. Along with the contribution of @mtzd. I found a tip for the solution based on the description of a problem that was in this post: https://stackoverflow.com/a/1925784/18600263. So the pos_save signal will be:

    from django.db import transaction
    
    GROUPS = ['SuperAdmins', 'Company', 'Unity', 'Staff']
    
    
    @receiver(post_save, sender=User)
    def user(sender: User, instance: User, **kwargs) -> None:
        group = Group.objects.get(name=GROUPS[instance.role])
        transaction.on_commit(lambda: instance.groups.set([group], clear=True))