menu

Questions & Answers

What is the proper way to set a UserCreationForm in Django?

I have an app that uses a custom User model called MyUser, a custom User manager, and a custom UserCreationForm. I'm trying to add the rest of the fields from the MyUser model to the UserCreationForm, but I keep getting the error: django.core.exceptions.FieldError: Unknown field(s) (username) specified for MyUser. What is the proper way to set a custom UserCreationForm? Here's my code.

Models.py

from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin
import uuid

class UserManager(BaseUserManager):
    def create_user(self, fname, lname, email, phone, password=None):
        if not email:
            raise ValueError('You must enter an email address')

        user = self.model(
            fname=fname,
            lname=lname,
            email=self.normalize_email(email),
            password=password,
            is_superuser=False
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_staffuser(self, email, password):
        user=self.create_user(self, fname, lname, email, phone, password)
        user.staff=True
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        user=self.create_user(self, fname, lname, email, phone, password)
        user.staff=True
        user.admin=True
        user.is_superuser=True
        user.save(using=self._db)
        return user



class MyUser(AbstractBaseUser, PermissionsMixin):
    fname=models.CharField(max_length=100)
    lname=models.CharField(max_length=100)
    email=models.EmailField(max_length=200, unique=True)
    phone=models.CharField(max_length=15)
    password=models.CharField(max_length=200)
    user_id=models.UUIDField(editable=False, primary_key=True, default=uuid.uuid4)
    is_active=models.BooleanField(default=True)
    staff=models.BooleanField(default=False)
    admin=models.BooleanField(default=False)    
    USERNAME_FIELD='email'
    required_fields=['fname', 'lname', 'email', 'password']

    @property
    def is_staff(self):
        #is the user staff?
        return self.staff

    @property
    def is_admin(self):
        #is the user an admin?
        return self.admin

    objects = UserManager()
    

Forms.py

from django import forms
from django.forms import ModelForm
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth import get_user_model

MyUser = get_user_model()

class MyUserLogin(AuthenticationForm):
    class Meta:
        model=MyUser
        fields=['email', 'password']
        
class MyUserSignup(UserCreationForm):
    class Meta(UserCreationForm):
        model=MyUser
        fields=UserCreationForm.Meta.fields + ('fname', 'lname', 'phone')

    def clean_email(self):
        email=self.cleaned_data.get('email')
        email_exists=MyUser.objects.filter(email__iexact=email).exists()
        if email_exists:
            raise self.add_error('There is already an account registered with that email.')

        return email
...

Comments:
2023-01-18 00:55:04
You're making us guess where the error happens. Please update the question to include the full error traceback message.
Answers(1) :

I have encountered the same issue just today and this is how I have solved it. When I created my custom user model I also created a custom UserCreation form. So when creating your forms make sure that you use the custom form you created and not the built in UserCreation Form that django provides. Example

This is the custom usercreation form I created

class CustomUserCreationForm(UserCreationForm): # This is the form that will be used to create a new user

class Meta:
    model = CustomUser
    fields = ('email',) # This is the fields that will be displayed in the form

And then this is how I used it

class CandidateSignUpForm(CustomUserCreationForm):
# code here
)

class Meta(CustomUserCreationForm.Meta):
    model = CustomUser

Also, if you're using the email for login instead of usernameand don't want to have the username field, You can remove it by setting username=None in your custom user model I hope that helps.