Custom User In Django
Introduction
Hello, In this post we will learn to make a Custom User Model in Django and we will also change the default login functionality of the Django Admin. We will use Email and Password to log in. Because few Customer Need a custom user Auth rather than going for a Default Auth system.
About custom user models
Django documents three ways to extend or replace the default User:
- Extend with a one-to-one field to
User - Substitute by subclassing from
AbstractUser: this preserves the fields and authentication methods - Substitute by subclassing from
AbstractBaseUser: this will not preserve the default fields, also impacting existing methods.
The third option is most involved, but it is the one we will choose, because it offers the freedom to customize registration with email rather than username.
First order of business: a new app named users to hold our custom user model. Name it however you please.
python manage.py startapp usersAnd add the following to settings.py. This indicates that we want to use a yet-to-be-created model users.User for authentication, replacing the default django.contrib.auth.models.User.
INSTALLED_APPS = [
...
'users',
]AUTH_USER_MODEL = 'users.User'When you need to refer to the custom user from other parts of your code, you can do that in any of the following ways:
from users import Userfrom customuser.settings import AUTH_USER_MODEL- use the
get_user_model()method fromdjango.contrib.auth
The third method is preferred — certain for code that you intend to re-use — as it deals with both the default and custom user models.
Create the Model Manager
The following model in users/models.py takes care of the custom User model.
Our User subclasses AbstractBaseUser, giving it the methods, but none of the default fields. We define our own fields, with the following being special cases:
USERNAME_FIELD: The name of the field that will serve as unique identifier (which will be theemailfield for us).EMAIL_FIELD: The name of the field that will be returned whenget_email_field_name()is called on a User instance.REQUIRED_FIELDS: Required fields besides thepasswordandUSERNAME_FIELDwhen signing up.is_staff: required by the admin.is_superuser: used by thePermissionsMixinto grant all permissions.is_active: indicates whether the user is considered “active”.
The UserManager subclasses the BaseUserManager and overrides the methods create_user and create_superuser. These custom methods are needed because the default methods expect a username to be provided. The admin app and manage.py will call these methods.
Use the custom user
Apply the migrations and create a superuser. You should be prompted for an Email: (and not a username) and no errors should occur.
python manage.py makemigrations users
python manage.py migrate
python manage.py createsuperuser
Email:
python manage.py runserverThe admin interface isn’t aware of the custom User model yet, so let’s take care of that in users/admin.py:
users/admin.py
After running the server, try to log into 127.0.0.1:8000/admin with the newly created superuser account. Try adding, editing and removing a few more user accounts for good measure.
You can also play around with the User model in the shell:
python manage.py shell
>>> from users.models import User
>>> u = User.objects.all()[0]
>>> u.set_password("newPassword")
>>> u.save()
>>> u.get_absolute_url()
# '/users/1/'It is worth taking the following from the Django docs into consideration concerning custom user models:
Think carefully before handling information not directly related to authentication in your custom user model.
It may be better to store app-specific user information in a model that has a relation with the user model. That allows each app to specify its own user data requirements without risking conflicts with other apps. On the other hand, queries to retrieve this related information will involve a database join, which may have an effect on performance.
Custom views for account management
We will next look at custom account-related operations, such as: logging in, signing up and viewing the account information. This section shows you how to do it with custom views. In most cases it would be better to use a library for these common operations, so feel free to skip ahead to the next section, where we will cover the same using the Allauth library.
The users should be able to log in, log out, sign up and view their profile. This is what that would look like in customuser/urls.py and users/urls.py.
customuser/urls.nl
users/urls.py
Get Punit Kulkarni’s stories in your inbox
Join Medium for free to get updates from this writer.
The urls should be self-explanatory. Notice that we use the built-in views for log in and log out and that we redirect to the /accounts/login on logging out.
The other two views — for profile and signup — are custom. Let’s take a look at users/forms.py and users/views.py
users/forms.py
users/views.py
The SignUpForm is derived from the built-in UserCreationForm, making use of the custom User model and replacing the username field with the email field.
Notice that the signup view also authenticates the user with their email:
user = authenticate(request, email=user.email, password=raw_password)The UserView is a “class based view” in which we override the get_objectmethod. It would normally expect a primary key in the request to get the correct instance, but here we can get the user instance directly from the request. We can be sure that the request has a user, because we added the login_required decorator to this view in urls.py.
These are the templates used for the account management:
No rocket science here. Start the server to test the url’s and authentication views.
Checkout the
custombranch of the repository to view the code at this point.
Using Allauth for account management
In the previous step we wrote the views for basic account management. As the requirements grow, this will result in more custom work. Fortunately there are a few libraries that are designed to handle this exact scenario. We will use the well-designed library “django-allauth”, at it works well with our custom User model.
It also handles additional requirements such as:
- email address verification
- enter a single password on sign up
- add social authentication (Oauth)
- reset passwords
pipenv install django-allauthConfiguration
Assuming you start with a default settings.py, these are the changes required by Allauth in settings.py:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', # existing backend
'allauth.account.auth_backends.AuthenticationBackend',
)INSTALLED_APPS = [
...
'django.contrib.sites', # make sure sites is included
'allauth',
'allauth.account',
'allauth.socialaccount',# the social providers
'allauth.socialaccount.providers.facebook',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.twitter',
...
]SITE_ID = 1ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'Edit urls.py:
urlpatterns = [
...
path('accounts/', include('allauth.urls')),
...
]And finally:
python manage.py migrate
python manage.py runserverYou will now have the basic functionality of our “custom” solution above and then some. The Allauth views and forms gracefully handle our User model with email authentication, after we provided this information in the settings.
Add Oauth providers
A further feature is the support of the OAuth authentication standard. This allows third party servers to perform the authentication. Users can also authorize your app to access profile data, such as the email address.
After starting your server, visit the admin pages (localhost:8000/admin/) and follow these steps:
- In the admin add a
Sitefor your domain, matchingsettings.SITE_ID. Set the Domain name tohttp://127.0.0.1:8000for development. - For each OAuth based provider, add a
Social Application. - Go to the provider (Google, etc) to add your client app, and add a redirect URL in the form of:
http://127.0.0.1:8000/accounts/google/login/callback/ - The provider will give you a Client ID and a Client Secret. Fill these in with the Social Application in the admin.
The official documentation has detailed instructions, and a list of social authentication providers.
Try it out
Allauth gives a range of account functionalities. Try them out:
- http://127.0.0.1:8000/accounts/signup/
- http://127.0.0.1:8000/accounts/logout/
- http://127.0.0.1:8000/accounts/login/
login with email or social account - http://127.0.0.1:8000/accounts/email/
manage email addresses - http://127.0.0.1:8000/accounts/password/change/
- http://127.0.0.1:8000/accounts/social/connections/
add social accounts to your user account
Conclusion
Implementing a custom user model is a non-trivial exercise, but made much easier by libraries such as Allauth. As it is recommended to start your project with a custom user model, I would advise to start Django projects from a pre-configured repository. Skip django-admin startproject and start with a template that has at least a custom user model.





