Add user to a group during creation

Hello everyone. I’m struggling to understand why the following code works using python manage.py shell but not using forms.ModelForm. What steps django takes in both scenarios?

# manager.py

from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import Group

# Works from python manage.py shell
class CustomUserManager(BaseUserManager):
    def create_user(self, username, email=None, password=None, **extra_fields):
        if email:
            email = self.normalize_email(email)

        user = self.model(username=username, **extra_fields)
        user.set_password(password)
        user.save()
        group, _ = Group.objects.get_or_create(name=user.type)
        user.groups.add(group)
        return user

    def create_superuser(
        self, username, email=None, password=None, **extra_fields
    ):
        extra_fields.setdefault("is_active", True)
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        return self.create_user(username, email, password, **extra_fields)

CustomUser model

class CustomUser(AbstractBaseUser, PermissionsMixin):
    class TYPE(models.TextChoices):
        ADMIN = "ADMIN", "Admin"
        STUDENT = "STUDENT", "Student"
        TEACHER = "TEACHER", "Teacher"
        STAFF = "STAFF", "Staff"

    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    username = models.CharField(max_length=100, unique=True)
    date_join = models.DateField(auto_now=True)
    type = models.CharField(max_length=10, choices=TYPE.choices)

    USERNAME_FIELD = "username"
    objects = CustomUserManager()
    default_choice = TYPE.ADMIN

    def save(self, *args, **kwargs):
        if not self.pk:
            self.type = self.default_choice
        return super().save(*args, **kwargs)


class Student(CustomUser):
    default_choice = CustomUser.TYPE.STUDENT
    # objects = StudentManager()

    class Meta:
        proxy = True

I created a ModelForm for User registration

# forms.py
class UserRegisterForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = (
            "type",
            "username",
        )

And finally the view


class UserRegister(View):
    def get(self, request):
        context = {
            "form": UserRegisterForm(),
            "p_form": ProfileForm(),
        }
        return render(request, "users/create_user.html", context)

    def post(self, request):
        type_ = request.POST.get("type")
        if type_ == "STUDENT":
            form = StudentForm(request.POST)
        elif type_ == "STAFF":
            form = StaffForm(request.POST)
        elif type_ == "TEACHER":
            form = TeacherForm(request.POST)
        else:
            form = UserRegisterForm(request.POST) # For ADMIN

        p_form = ProfileForm(request.POST)
        if form.is_valid() and p_form.is_valid():
            user = form.save()
            return redirect(reverse('login'))
        context = {
            "form": UserRegisterForm(),
            "p_form": ProfileForm(),
        }
        return render(request, "users/create_user.html", context)

What code? Please be specific about what command you’re entering in the shell, and what code you think is in the view that is doing that same thing.

Thanks for your reply.
What I want is to add a user to a specific group based on its type during the creation process, from python manage.py shell I can do this

from users.models import CustomUser, Student

s = Student.objects.create_user(username='student1', password='student1') # This will create and add 'student1' to group 'STUDENT'
u = CustomUser.objects.create_user(username='admin', password='admin') # This will create and add 'admin' to 'ADMIN' group

However, using forms.ModelForm a user is created but not added to a group and I’d like to know what I am missing.

What you are missing is that your view isn’t calling the create_user method of the CustomUserManager. You’re calling form.save, which is eventially going to call the model’s save method. But at no time in that process is create_user being called.

Oh, thanks! I’m clear now. If you don’t mind, would you suggest me perhaps an appropriate way of doing this?

Sure, create the group in your view after the user has been created.

1 Like

I can’t thank you enough.