Search code examples
djangopython-3.8django-2.2

How to assign users in groups from Django views?


I have CRUD operations for users, which can be done only from the admin role. I have 6 different roles, that I made by creating groups and assign users to specific group from the admin panel.

My question is is there some way to include these group fields with drop down menu when admin create new user, so he can choose what group to assign the new user but not from the admin panel?

any help would be appreciated :)

model.py

class CustomUserManager(BaseUserManager):

    def create_user(self, email, password, **extra_fields):

        if not email:
            raise ValueError(_('The Email must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, password, **extra_fields):

        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True.'))
        return self.create_user(email, password, **extra_fields)


class CustomUser(AbstractUser):

    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    def __str__(self):
        return self.email

    username                        = models.CharField(max_length=30, blank=True, default='')
    is_superuser                    = models.BooleanField(default=True)
    is_admin                        = models.BooleanField(default=True)
    is_employee                     = models.BooleanField(default=True)
    is_headofdepartment             = models.BooleanField(default=True)
    is_reception                    = models.BooleanField(default=True)
    is_patient                      = models.BooleanField(default=True)
    is_active                       = models.BooleanField(default=True)
    is_staff                        = models.BooleanField(default=True)

forms.py

class UserForm(ModelForm):
    class Meta:
        model = CustomUser
        fields = ['email', 'password',]

useradd.html

<h1 class="display-4">Add new user</h1>
            <form action="" method="post" autocomplete="off">
                {% csrf_token %}
                {{ form.as_p }}
                    <button type="submit" class="btn btn-success">Save </button>

views.py

@login_required
@admin_only
def users(request):
    context = {'users': CustomUser.objects.all()}
    return render(request, 'users.html', context)

@login_required
def users_add(request):
    if request.method == "POST":
        form = UserForm(request.POST)
        if form.is_valid():
            users = CustomUser.objects.create_user(**form.cleaned_data)
            #login(request, users)
            # redirect, or however you want to get to the main view
            return redirect('feedback:users')
    else:
        form = UserForm() 

    return render(request, 'useradd.html', {'form': form}) 

Solution

  • You can use ModelChoiceField to include select widget in your form. So please try this code:

    forms.py

    from django.contrib.auth.models import Group
    from django.forms import ModelForm, ModelChoiceField
    
    from app.model import CustomUser
    
    
    class UserForm(ModelForm):
    
        class Meta:
            model = CustomUser
            fields = [
                'email',
                'password',
            ]
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['group'] = ModelChoiceField(
                queryset=Group.objects.all(),
                empty_label='No group'
            )
    

    Change CustomUserManager.create_user method in model.py

    from django.contrib.auth.models import Group
    
    
    class CustomUserManager(BaseUserManager):
    
        def create_user(self, email: str, password: str, group: Group, **extra_fields):
            if not email:
                raise ValueError(_('The Email must be set'))
    
            email = self.normalize_email(email)
            user = self.model(email=email, **extra_fields)
            user.set_password(password)
            user.save()
    
            if group is not None:
                group.user_set.add(user)
    
            return user