# Custom add user form in Django Admin?

**URL:** <https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443>\
**Category:** The Admin\
**Created:** [October 12, 2022, 1:57pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443 "2022-10-12T13:57:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![tellSlater](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tellslater/32/10248_2.png) [@tellSlater](https://forum.djangoproject.com/u/tellSlater)\
**Post date:** [October 12, 2022, 1:57pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/1 "2022-10-12T13:57:01Z")

</div>

How can you use a custom “add user” form along with a custom “user model”? After defining a custom User model for email login, it is important that the “add user” form asks for an email and not a username to create a user.

This is the form that appears after clicking “add user” in Django admin. I need to turn the Username field into an Email field since I am using email for authentication in my custom user model.

![image](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/2X/4/4a5f9f939ae8dd6383948e7db71dc837170719aa.png)

Changing the User’s email field to unique=True, blank=False and USERNAME\_FIELD = ‘email’ doesn’t work. I have also tried attaching custom "UserCreationForm"s to UserAdmin but that didn’t help either.

---

<div class="post-metadata">

**Author:** ![rasulkireev](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/rasulkireev/32/1151_2.png) [@rasulkireev](https://forum.djangoproject.com/u/rasulkireev)\
**Post date:** [October 12, 2022, 2:40pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/2 "2022-10-12T14:40:29Z")

</div>

Can you share the contents of the `admin.py` and `models.py`?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [October 12, 2022, 2:50pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/3 "2022-10-12T14:50:07Z")

</div>

What specifically do you mean by “doesn’t work”?

If you have your model defined correctly, setting USERNAME\_FIELD _should_ result in the form field named “Username” storing the entry there into the email field.

---

<div class="post-metadata">

**Author:** ![tellSlater](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tellslater/32/10248_2.png) [@tellSlater](https://forum.djangoproject.com/u/tellSlater)\
**Post date:** [October 12, 2022, 3:20pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/4 "2022-10-12T15:20:27Z")

</div>

My admin.py:

> ```
> from django.contrib import admin
> from django.contrib.auth.admin import UserAdmin
> from django.contrib.auth.forms import UserCreationForm
> from django.forms import EmailField
> from .models import Account
> 
> class UserCreateForm2(UserCreationForm):
> class Meta:
> model = Account
> fields = ('email',)
> field_classes = {"email": EmailField}
> 
> # placeholders = ['example@email.com', 'Username',]
>     
>     
> class AccountAdmin(UserAdmin):
> form = UserCreateForm2
> add_form = UserCreateForm2
> list_display = ('email', 'username', 'date_joined', 'last_login', 'is_staff', )
> search_fields = ('email', 'username')
> readonly_fields = ('date_joined', 'last_login')
> 
> def get_form(self, request, obj=None, **kwargs):
> """
> Use special form during user creation
> """
> return self.form
> 
> admin.site.register(Account, AccountAdmin)
> 
> ```

My models.py:

> ```
> from django.db import models
> from django.contrib.auth.models import BaseUserManager, AbstractUser
> 
> class MyAccountManager(BaseUserManager):
> def create_user(self, email, username, password=None):
> if not email:
> raise ValueError("Users must have an email address")
> if not username:
> raise ValueError("Users must have a username")
> user = self.model(
> email=self.normalize_email(email),
> username=username
> )
> user.set_password(password)
> user.save(using=self._db)
> return user
> 
> def create_superuser(self, email, username, password):
> user = self.create_user(
> email=self.normalize_email(email),
> password=password,
> username=username,
> )
> user.is_staff = True
> user.is_superuser = True
> user.save(using=self._db)
> return user
> 
> class Account(AbstractUser):
> email = models.EmailField(verbose_name="email", max_length=60, unique=True)
> 
> USERNAME_FIELD = 'email'
> REQUIRED_FIELDS = ['username']
> 
> objects = MyAccountManager()
> 
> def __str__ (self):
> return self.email
> 
> def has_module_perms(self, app_label):
> return True
> 
> ```

The result is this form when I add users from within the admin:

![image](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/2X/4/4a5f9f939ae8dd6383948e7db71dc837170719aa.png)

When the form is saved, the value of the "Username: " field is saved as the user’s username and the user object is created having no email! The email can be added afterwards though. I was looking for a way to substitute the "Username: " field in that form with an "Email: " field since I am using email as my USERNAME\_FIELD and it seems more sensible to have it that way.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [October 12, 2022, 4:21pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/5 "2022-10-12T16:21:37Z")

</div>

Note that if you’re working from the example at [Customizing authentication in Django | Django documentation | Django](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#a-full-example), you’re building from the wrong base class. You want to inherit your model from `AbstractBaseUser` and not `AbstractUser`.

You also won’t want to include _any_ references to an independent field named `username` - that’s only going to confuse the issue. (Notice the lack of references to a `username` field in the `MyUserManager` class.)

---

<div class="post-metadata">

**Author:** ![tellSlater](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tellslater/32/10248_2.png) [@tellSlater](https://forum.djangoproject.com/u/tellSlater)\
**Post date:** [October 13, 2022, 6:58am UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/6 "2022-10-13T06:58:11Z")

</div>

I am inheriting from the AbstractUser and not the AbstractBaseUser because it comes with all the default fields and usability. The reason I am overriding the username field here is because I was trying to define it as “blank=True” or make it optional since I want to use USERNAME\_FIELD = ‘email’. I don’t think these actions should stand in the way of changing that “Username:” field in the “Add new” form.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [October 13, 2022, 12:06pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/7 "2022-10-13T12:06:46Z")

</div>

Quoting directly from the docs:

- [Specifying a custom user model](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#specifying-a-custom-user-model)

> The easiest way to construct a compliant custom user model is to inherit from [`AbstractBaseUser`](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser). [`AbstractBaseUser`](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser) provides the core implementation of a user model, including hashed passwords and tokenized password resets. You must then provide some key implementation details:

and

- [Extending Django’s default `User`](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#extending-django-s-default-user)

> If you’re entirely happy with Django’s [`User`](https://docs.djangoproject.com/en/4.1/ref/contrib/auth/#django.contrib.auth.models.User) model, but you want to add some additional profile information, you could subclass [`django.contrib.auth.models.AbstractUser`](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#django.contrib.auth.models.AbstractUser) and add your custom profile fields, although we’d recommend a separate model as described in [Specifying a custom user model](https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#specifying-custom-user-model). `AbstractUser` provides the full implementation of the default [`User`](https://docs.djangoproject.com/en/4.1/ref/contrib/auth/#django.contrib.auth.models.User) as an [abstract model](https://docs.djangoproject.com/en/4.1/topics/db/models/#abstract-base-classes).

Regarding this second quote, you’re going well beyond “add some additional profile information”.

So yes, you can continue to try and make this work this way, or you can take the advice and guidance of the documentation and replace your base class.

---

<div class="post-metadata">

**Author:** ![tellSlater](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tellslater/32/10248_2.png) [@tellSlater](https://forum.djangoproject.com/u/tellSlater)\
**Post date:** [November 1, 2022, 2:35pm UTC](https://forum.djangoproject.com/t/custom-add-user-form-in-django-admin/16443/8 "2022-11-01T14:35:44Z")

</div>

I finally managed to customize the add user form in the admin by overriding the “add\_fields” attribute of the UserAdmin class. Here is how my UserAdmin looks like now:

> ```
> class AccountAdmin(UserAdmin):
> # form = UserCreateForm2
> # add_form = UserCreateForm2
> list_display = ('email', 'date_joined', 'last_login', 'is_staff', )
> search_fields = ('email', )
> readonly_fields = ('date_joined', 'last_login')
> fieldsets = (
> (None, {"fields": ("email", "password")}),
> (_("Personal info"), {"fields": ("first_name", "last_name")}),
> (
> _("Permissions"),
> {
> "fields": (
> "is_active",
> "is_staff",
> "is_superuser",
> "company",
> "groups",
> "user_permissions",
> ),
> },
> ),
> (_("Important dates"), {"fields": ("last_login", "date_joined")}),
> )
> add_fieldsets = (
> (
> None,
> {
> 'classes': ('wide',),
> 'fields': ('email', 'first_name', 'last_name', 'password1', 'password2'),
> },
> ),
> )
> 
> ```

And the result is:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/2X/e/e03b30dac8b215c67c3b0cc0cc1e7c042bc97362.png)
