Django Custom Authentication With email

Aakash Verma
Analytics Vidhya
Published in
9 min readJul 16, 2020
A guy with a card in his hand having python written over it

Hi there , I trust you are doing well , While building websites it is first requirement by the clients that the user should be authenticated via email and not username, as Django by default provides authentication using username only . It becomes necessity to create a custom user authentication system that uses e-mail to authorize user and allow to login into the system. So In this article we will be making a custom user authentication system which will use email to authenticate users .

Let’s Start...

Pre-requisites: — Well there is not much of knowledge needed but I assume you are well acquainted with basic python understanding and know how web works …!!!

step 1: — Download and install Python as per your system Os . (Link)

mkdir login_system
cd login_system

make a directory named login_system in your desktop or wherever you want to store your project into .

step 2: — Set up a virtual environment around login_system . It is recommended that you use virtualenv to create isolated Python environments, so that you can use different package versions for different projects, which is far more practical than installing Python packages system-wide

pip install virtualenv

After you install virtualenv, create an isolated environment with the following command:

virtualenv env

This will create a env/ directory, including your Python environment. Any Python libraries you install while your virtual environment is active will go into the env/lib/python3.6/site-packages directory.

Run the following command to activate your virtual environment:

source env/bin/activate          ## for mac usersenv\Scripts\activate\            ## for windows user"""
You can deactivate your environment at any time with the deactivate command.
activate
"""

step 3: — Installing Django

Run the following command at the shell prompt to install Django with pip:

pip install Django==3.0.7

Django will be installed in the Python site-packages/ directory of your virtual environment. Now, check whether Django has been successfully installed. Run python on a terminal, import Django, and check its version, as follows:

>>> import django 
>>> django.get_version()
‘3.0.7’

If you get the preceding output, Django has been successfully installed on your machine.

Now we will create a Django project inside our login_system directory

What is Django project ?

Django project is a place where all the database configuration, server settings, app URL settings files are located. It can have multiple apps inside it .

django-admin.py startproject mysite

Above command will create a folder named mysite inside our login_system directory . If you look inside this folder it contains some files , those are,

manage.py: This is a command-line utility used to interact with your project. It is a thin wrapper around the django-admin.py tool. You don’t need to edit this file.

mysite/: This is your project directory, which consists of the following files:

__init__.py: An empty file that tells Python to treat the mysite directory as a Python module.

settings.py: This indicates settings and configuration for your project and contains initial default settings.

urls.py: This is the place where your URL patterns live. Each URL defined here is mapped to a view.

wsgi.py: This is the configuration to run your project as a Web Server Gateway Interface (WSGI) application.

Now its time to create a app in which we will be putting our logic ,

cd mysite
python manage.py startapp account

Above command will create account folder inside our root mysite directory,

now tree structure must look something like this,

#Directory Tree Structure 
login_system/
myenv/
mysite/
account/
__init__.py
admin.py
apps.py
models.py
views.py
tests.py
mysite/
__init__.py
asgi.py
settings.py
urls.py
wsgi.py
manage.py

Edit settings.py of your project folder ,

#settings.py
import os
...
...
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'account', #new
]

This will let Django project know that an app named account exists .

now when inside mysite root directory run this command

python manage.py runserver

This command starts the development server so that we can test our application in development phase . Now go to http:/.localhost:8000 or http:/.127.0.0.1:8000

If you see the above page running that means our setup is successfull …

Why custom user model is a right choice for you ?

Keeping all the user related information in one model removes the need of additional or complex database queries to retrieve related models . Also it may be more suitable to store app-specific user information in a model that has a relation with your custom user model and allows each app to have its own user data requirements without conflicting or breaking assumptions of each apps .

Advantage of Custom User Model : — If you use default authentication provided by Django then your model must have a single unique field that can be used for identification purposes. This can be a username, an email address, or any other unique attribute. A non-unique username field is allowed if you use a custom authentication backend that can support it.

The easiest way to construct a custom user model is to inherit from AbstractBaseUser. AbstractBaseUser provides the core implementation of a user model, including hashed passwords resets. You must then provide some key implementation details like username_field, email_field, is_active etc. I will walk you through full implementation of such custom user model . So lets Start here ….

go to models.py file in your accounts app and paste following lines of code . . .

account/models.py

In above lines of code I have defined an Account class having the basic fields , i have also specified USERNAME_FIELDS value as email to let Django know i want to use email as a unique user identifier during authentication .

I have mentioned REQUIRED_FIELDS with value of username as we want users to provide their username while registering . It’s totally optional and you can omit that .
Notice that I have created a AccountManager class which acts a manager for our Account class and it extends BaseUserManager and need two additional methods create_user() and create_superuser() . I have also provided some basic validation to make sure user enter correct details .

After creating model for our User Account we will run migrations .The migrations can be said as Django’s way of propagating changes you make to your models into your database schema .

run following command in your command line,

python manage.py makemigrations app
python manage.py migrate

you will notice in your console something like this

Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, account
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_update_proxy_permissions... OK
Applying sessions.0001_initial... OK

You will notice something like above in your console . That is django applying migrations to the database.

Now create a forms.py file in account folder and paste following lines of code .

In above lines of code I have defined classes for Registering news users , Authenticating Registered users and Updating user Information i.e. RegistrationForm, AccountAuthenticationForm and AccountUpdateform respectively .

Registration Form inherits UserCreationForm in Django which is used to sign up new users into Django authentication system or our custom authentication system . It accepts four fields username, email, password , and confirm password fields .

AccountAuthenticationForm and AccountUpdateform are Account model forms and has username , email , and password fields .

We need to have also extended __init__ methods to provide additional styling(Bootstrap classes) to individual fields of each form .

In AccountUpdateform we need to override clean_email and clean_username methods so that every user hae unique email and username .

Now we have to edit views.py file in our Account Folder . Paste the following Lines of code in your views.py file

In above lines of code we have four view functions defined …

home :- This function renders base.html i.e our home page

registration_view :- This function renders registration form which allows user to sign up in to our system .First we check whether the requested method is POST and then validate the form using is_valid()(This validates form against the field types mentioned in corresponding models.py class ) method. form.save() method creates and saves a database object from the data bound to the form . i.e. it created a database instance of the data that is presented with the form as per our model class .

further we get email and password using form.cleaned_data.get() method which has all the values stored that were passed by the user and use the data to authenticate user using built-in authenticate method provided by Django which check and validates user password and email and hence we use in- built login method to login user to the system and redirect them to home page . We also display a Registration Successful message using message framework provided by Django and in else part we display the any error message if in case it occurs .

login_view -: Login view works in same fashion as registration_view , It checks whether account with the supplied email id exists . If yes user is logged in else he/she is displayed with error messages. Here we also check whether user is already authenticated or not to prevent already logged in user from having login page again as it is of no use.

logout_view :- This is pretty simple function which uses in-built logout function to log users out from the system . it takes request as parameter which has information related to logged In user .

account_view :- In this view we will be rendering AccountUpdateform through which user can update their details . we need to pass user instance so that form is already filled with initial values of user information and when user edits and click on save_changes it gets updated from their .

Make Sure You import all the neccessary things so that you won’t face any error.

Templates:- Let’s make templates for our views so that we can have neat and tidy look of our login_system . For this I will be using Bootstrap , you are free to use either pure CSS or Bootstrap

We need to generate a base template so that our other template files can extend the base template and we need not to write the same code in every file . Create a templates folder in your root project directory and in settings.py file edit the following :

so we have set the path of our templates folder to which django look for when finding the template files for particular view function .

Now inside templates folder that we created , create a base.html file and add the following code in it .

adding login.html template , create a folder named accounts in your template folder(this is usually done to keep the app specific template files in one place ) and create a file name login.html and add the following code .

Register.html

create a new file named register.html in your accounts folder in templates and add following code :

userprofile.html

create a file names userprofile.html in accounts folder of your templates and add the following code :

all the template files are pretty much understandable as it is not much to gain and its just simple html To be honest.

URL’s :-

Now that we have done with view and templates we will set up URL for our site . Go to url.py folder of our mysite project . and add these code.

in above mysite/urls.py file we included our accounts app urls.py file so that Django know where to serve the request for our views .

Now create a new urls.py file in our account folder and add the following code in it.

This urls.py file we are creating will handle all the urls for the view functions for our app . we just need to supply the right view function and it will serve the request in the provided endpoint .

Now that everything is set lets run the server ,

Go to terminal and in your project directory , make sure your virtual environment is activated , run the following command,

python manage.py runserver

This runs the built-in development server that comes with Django.

Now in your web browser go to http://127.0.0.l:8000/account/register , you will notice that our registration page gets loaded there. Try registering a new user there . Once done you will be redirected to a our home page with the welcome message .Try changing the your details like email and username . If you face any errors kindly revisit each code and cross check if you made any errors or not .And if it further exists then feel free to write your errors in comments I will try to solve them each… Happy Coding !!!

--

--

Aakash Verma
Analytics Vidhya

Computer Science Undergrad ,Tech Enthusiast , Loves writing about Technology