Django custom user creation not displaying custom fields in admin site
I'm trying to create a cutom user in my Django with custom fields like first_name, last_name, date_of_birth, gender, email, etc. So for this I have overridden AbstractBaseUser
for my custom user UserCreationForm
to create a new user and UserChangeForm
change the values of the user fields.
Models.py
class AppUserManager(BaseUserManager):
"""
Manager for class AppUser
"""
def _create_user(self, username, password, first_name, last_name,
date_of_birth, email, gender, is_staff, is_superuser,
**extra_fields):
"""
Creates and saves a User with the given username, email and password.
"""
now = timezone.now()
if not username:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
user = self.model(username=username,
first_name=first_name, last_name=last_name,
date_of_birth=date_of_birth, email=email, gender=gender,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, last_login=now,
date_joined=now, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, password, first_name, last_name, date_of_birth, email, gender, **extra_fields):
return self._create_user(username, password, first_name, last_name,
date_of_birth, email, gender, False, False,
**extra_fields)
def create_superuser(self, username, password, first_name, last_name, date_of_birth, email, gender, **extra_fields):
return self._create_user(username, password, first_name, last_name,
date_of_birth, email, gender, True, True,
**extra_fields)
class AppUser(AbstractBaseUser, PermissionsMixin):
"""
User for Application
"""
username = models.CharField(verbose_name='username', max_length=30, unique=True,
help_text='Required. 30 characters or fewer. Letters, digits and '
'@/./+/-/_ only.',
validators=[
validators.RegexValidator(r'^[\w.@+-]+$', 'Enter a valid username.', 'invalid')
])
first_name = models.CharField(verbose_name='first name', max_length=30)
last_name = models.CharField(verbose_name='last name', max_length=30)
date_of_birth = models.DateField(verbose_name='birth date')
email = models.EmailField(verbose_name='email address', unique=True)
GENDER_CHOICES = (
('m', 'Male'),
('f', 'Female'),
)
gender = models.CharField(verbose_name='gender', max_length=1, choices=GENDER_CHOICES)
is_staff = models.BooleanField(verbose_name='staff status', default=False,
help_text='Designates whether the user can log into this admin '
'site.')
is_active = models.BooleanField(verbose_name='active status', default=True,
help_text='Designates whether this user should be treated as '
'active. Un select this instead of deleting accounts.')
date_joined = models.DateTimeField(verbose_name='date joined', default=timezone.now)
objects = AppUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['first_name', 'last_name', 'date_of_birth', 'email', 'gender']
class Meta:
verbose_name = 'user'
verbose_name_plural = 'users'
db_table = 'app_users'
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Returns the short name for the user."""
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email], **kwargs)
admin.py
class CustomUserCreationForm(UserCreationForm):
"""
A form for creating new users. Includes all the required fields, plus a repeated password.
"""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password Confirmation', widget=forms.PasswordInput)
first_name = forms.CharField(label='First Name') # Custom Required Field. and other fields should go same way
class Meta(UserCreationForm.Meta):
model = AppUser
fields = ('username', 'first_name', 'last_name', 'date_of_birth', 'email', 'gender')
def clean_username(self):
username = self.cleaned_data["username"]
try:
AppUser.objects.get(username=username)
except AppUser.DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords do not match.")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class CustomUserChangeForm(UserChangeForm):
password = ReadOnlyPasswordHashField(label="password",
help_text="""Raw passwords are not stored, so there is no way to see this
user password, but you can change the password using <a href=\"password/\">
this form</a>.""")
class Meta(UserChangeForm.Meta):
model = AppUser
fields = (
'username', 'first_name', 'last_name', 'date_of_birth', 'email', 'gender',
'password', 'is_active', 'is_staff', 'is_superuser', 'user_permissions'
)
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class AppUserAdmin(UserAdmin):
"""
"""
form = CustomUserChangeForm
add_form = CustomUserCreationForm
list_display = ('username', 'first_name', 'last_name', 'email',)
list_filter = ('is_superuser',)
fieldsets = (
(None, {'fields': (
'username', 'first_name', 'last_name', 'date_of_birth', 'email', 'gender',
)}),
('Permissions', {'fields': (
'is_active', 'is_superuser', 'is_staff',
)}),
)
search_fields = ('username', 'email', 'first_name', 'last_name',)
ordering = ('username', 'email',)
admin.site.register(AppUser, AppUserAdmin)
I created a superuser from the command line. But in the form for adding a user, only the fields "Username", "Password" and "Confirm password" are displayed.
So how can I get the fields to create a custom form displaying the required fields?
After submitting it gives me an error:
Exception Type: IntegrityError at /admin/users/appuser/add/
Exception Value: Column 'date_of_birth' cannot be null
This is the correct form to add a user. Since the help text is formulated on top of the form, the username and password are set first, then you will see the rest of the fields. If you are editing an existing user, you will see everything as well.