Django - Creating A Custom User Model
Django - Creating A Custom User Model
Model in Django
The built-in User model and authentication functionality in Django are fantastic.
For a long time, it’s been a Django mainstay. It is Django’s source of preference
over alternative web frameworks like Flask, FastAPI, AIOHttp, and others. When a
username and password contained in the user model need to be authenticated
against a service other than Django’s default, authentication backends provide an
expandable system.
You can grant specific permissions to your models, which can be validated using
You’ll need to alter the default user model’s functionality now and then. Assume
you no longer require a username field. Alternatively, you may make the email
field your default “username” field. We’ll need to tweak our regular Django User
complicated system. When possible, stick to the original settings. In other words,
if you don’t have to, don’t develop a unique user model; Foreign Keys are perfect
for that.
You can either extend the default User model or create a new one. In this article,
organization may already have an LDAP server set up that maintains each
employee’s username and password. If users had different accounts in LDAP and
authentication sources to handle this scenario. You can either change Django’s
own. You can develop a proxy model based on User if the changes you need are
simply behavioral and don’t require any modifications to the database. It allows
for any proxy model’s characteristics, such as default ordering, custom managers,
You can use an OneToOneField to a model containing the fields for additional
information if you want to store a user’s information. Because it may keep non-
referred to as a profile model. You could, for example, establish a Staff model:
class Staff(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.CharField(max_length=100)
Using Django’s standard related model conventions, you may retrieve the related
information for an existing Staff Ann Keen, who has both a User and an Employee
model:
u = User.objects.get(username='ann')
anns_department = u.employee.department
In your app’s admin.py, define an InlineModelAdmin. For this example, we’ll use a
StackedInline and add it to a UserAdmin class that is registered with the User
class: To add a profile model’s fields to the user page in the admin, define an
InlineModelAdmin and add it to a UserAdmin class that is registered with the User
class:
class UserAdmin(MainUserAdmin):
inlines = (StaffInline,)
# Re-register UserAdmin
admin.site.unregister(CustomUser)
admin.site.register(CustomUser, UserAdmin)
These profile models are nothing remarkable; they’re just Django models with a
one-to-one relationship with a user model. As a result, they aren’t produced
automatically when a user is created; however, a
django.db.models.signals.post_save might be used to create or update relevant
models as needed.
Using related models necessitates more queries or joins to retrieve the relevant
data. Depending on your needs, a bespoke user model with the associated fields
model within your project’s apps may justify the increased database burden.
User model isn’t always suitable. For example, using an email address rather than
custom model, Django allows you to alter the default user model. It is where you’ll
store your custom user model, and in our case, we will call it accounts. It explains
the name of the Django model you want to use as your user model and the label
You may either use the Django example or the one we’ve provided below. We’ll
make it easier for you here.
# accouts/models.py
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='user email address',
max_length=100,
unique=True,
)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] # Email & Password are required by default.
def get_full_name(self):
# users identification is by email
return self.email
def get_user_short_name(self):
# user identification is by email
return self.email
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
# return true if user has the necessary permissions
return True
@property
def is_staff(self):
# returns true if user is a staff
return self.is_staff
@property
def is_admin(self):
# returns true if user is admin member
return self.is_admin
So, what precisely is the USERNAME_FIELD? That’ll be how Django will recognize
this user. It takes the place of the built-in username field with whatever you
specify. In this situation, we choose to use an EmailField, but you could instead
use a phone number.
use Django’s UserManager if your user model has the same email, is_staff, date
user. However, if your user model has different fields, you’ll need to define a
custom manager that extends BaseUserManager and provides two additional
methods:
The User Manager in Django has built-in methods. For our custom user model to
perform correctly, we must customize them.
class UserManager(BaseUserManager):
"""
if not, email:
raise ValueError('Cannot create a user without an email address ')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
update settings.py
AUTH_USER_MODEL = 'accounts.User'
It gives other developers and our future selves the kind of peace of mind that only
well-written code can deliver. In fact, get_user_model is one of those components
that the core Django developers settled on a long time ago. But what about
foreign keys created by users? You’ll come across this issue at some point:
class SomeModel(models.Model):
user = models.ForeignKey(…)
You’ll make use of the option settings. AUTH USER MODEL every time, regardless
of whether the user model has been customized. As a result, it will appear like
this:
User = settings.AUTH_USER_MODEL
class SomeModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
AUTH_USER_MODEL because it’s a model form based on our user model, but let’s
# accounts/forms.py
User = get_user_model()
class RegisterForm(forms.ModelForm):
"""
The default
"""
password = forms.CharField(widget=forms.PasswordInput)
password_2 = forms.CharField(label='Confirm Password',
widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email']
def clean_email(self):
'''
Verify email is available.
'''
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean(self):
'''
Verify both passwords match.
'''
cleaned_data = super().clean()
password = cleaned_data.get("password")
password_2 = cleaned_data.get("password_2")
if password is not None and password != password_2:
self.add_error("password_2", "Your passwords must match")
return cleaned_data
class UserAdminCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password = forms.CharField(widget=forms.PasswordInput)
password_2 = forms.CharField(label='Confirm Password',
widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email']
def clean(self):
'''
Verify both passwords match.
'''
cleaned_data = super().clean()
password = cleaned_data.get("password")
password_2 = cleaned_data.get("password_2")
if password is not None and password != password_2:
self.add_error("password_2", "Your passwords must match")
return cleaned_data
class UserAdminChangeForm(forms.ModelForm):
"""
The form is responsible for user updates and has all user fields
. It also uses the admin's
password hash for display.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ['email', 'password', 'is_active', 'admin']
def clean_password(self):
# return the first value irrespective of what is provided by the user
return self.initial["password"]
admin.site.unregister(Group)
class UserAdmin(MainUserAdmin):
# These forms forms to add and change user instances
form = UserAdminChangeForm
add_form = UserAdminCreationForm
admin.site.register(User, UserAdmin)
is one of the limitations of custom user models. Proxy models must have a
concrete base class; establishing a custom user model disables Django’s ability to
If your project uses proxy models, you must either adapt the proxy to extend the
user model in use or merge the behavior of your proxy into your User subclass.
Conclusion
Although the authentication provided by Django is enough in most circumstances,
you may have requirements that are not covered by the defaults. Understanding
what parts of the supplied system are expandable or replaceable is necessary for
https://www.codeunderscored.com/creating-a-custom-user-model-in-django/