Django User Registration with Email Confirmation

In this Python Django tutorial, we are going to learn about user login registration in the Django framework and after that, we will also send the confirmation email to confirm the user registration through email.

How to create User Registration with Email Confirmation in Django?

Here in this tutorial, we are going to create a user registration with an email confirmation application.

  • First, we will set up a basic Django app and configure it.
  • Generating tokens to authenticate our users through email confirmation.
  • Creating models, views, and templates.
  • Create Email backend and settings and see SMTP server settings.

Step 1: Setup a Django Project

Firstly, we will create a virtual environment.

We will create a virtual environment in the folder(create a folder in case not created) in which we are going to set up our User registration Django project. To create a virtual environment, use these commands in a command prompt(as an administrator) or VS code terminal.

> python -m auth-env

Now, we have successfully created a virtual environment i.e. auth-env.

Follow the below command to activate the virtual environment.

> auth-env\Scripts\activate

We have successfully created and activated a virtual environment auth-env in our Django project. It will appear in your terminal as shown in the picture below.

Django user registration
Virtual-env in our Python Django user registration app

Installing Django in our virtual environment.

Every time we create a virtual environment we need to install the package requirement of our project. Now we will install Django in our virtualenv using the pip command.

> pip install django

Creating a Python Django Project

To create a Django project in Python run the following commands in the terminal.

> django-admin startproject UserAuth

We can see in the sidebar of VS code that our project UserAuth is created and it automatically generated some files and directories as shown in the picture below.

user registration app django
Created project in Django application

Moving to the project directory

To run our project on the server, we need to move to the project directory in the terminal using the following command.

> cd UserAuth

Creating a Django Application

For code organization and easy debugging, we will create a Django app named accounts in our project directory using the below command.

> python manage.py startapp accounts

Till now, we have successfully created our project UserAuth and application accounts.

Configure and Registering App

For app configuration, we need to go to the settings.py file which is under our project directory UserAuth then go to the INSTALLED APPS list and register the ‘accounts’ app. The code is mentioned below for better understanding.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts',
]

URL Configuration

Now we need to add a URL path in our urls.py file. To design URLs in the app there is a Python module URL configuration. This module is pure Python code and is a mapping between URL path expressions to Python functions.

So, we will add the below code in our urls.py file of the UserAuth Folder.

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('',include('accounts.urls')),
    path('admin/', admin.site.urls),
]

Creating templates in our app accounts.

In this step, we will create some templates in HTML format in our app directory accounts. Make sure to use exact word templates. For creating templates click on accounts and create new folder templates and in that templates create an HTML file base.html and its code is mentioned below.

<!doctype html>
<html lang="en">
  <head>
   
    <title>Django app</title>
    
  </head>
  <body>
    {% block content %}

    {% endblock %}

Now we will create three more templates login.html, home.html, and register.html within the templates folder, and after that, we will register both files in views of our application. follow the below code login.html file.

{% extends "base.html" %}
    
    {% block content %}

    <div class="global-container">
        <div class="card login-form">
        <div class="card-body">
            <h3 class="card-title text-center">Log in to user account</h3>
            <div class="card-text">
                
                <form>
                    
                    <div class="form-group">
                        <label for="exampleInputEmail1">Email address</label>
                        <input type="email" class="form-control form-control-sm" id="exampleInputEmail1" aria-describedby="emailHelp">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">Password</label>
                        <a href="#" style="float:right;font-size:12px;">Forgot password?</a>
                        <input type="password" class="form-control form-control-sm" id="exampleInputPassword1">
                    </div>
                    <button type="submit" class="btn btn-primary btn-block">Sign in</button>
                    
                    <div class="sign-up">
                        Don't have an account? <a href="#">Create One</a>
                    </div>
                </form>
            </div>
        </div>
    </div>
    </div>

    {% endblock %}

After creating login.html we will use the whole code of login.html in home.html and register.html and for now, just change the title in the register.html file.

User authentication in Pyhton Django
Registration of user in o Django app error

Read Python Django import functions

Creating URLs in our application

We are going to create URLs in our accounts app. The code which is used in app urls.py is mentioned below.

from django.contrib import admin
from django.urls import path
from .views import *


urlpatterns = [
    path('', home , name='home'),
    path('register' ,  register_attempt , name='register_attempt'),
    path('login' , login_attempt , name='login_attempt'),
]

Creating views in the app.

In the views of accounts app, we will create a route for login and register HTML pages.

from django.shortcuts import render


def home (request):
    return render (request , 'home.html')

def login_attempt(request):
    return render (request, 'register.html')

def register_attempt (request):
    return render(request , 'login.html')

After this step, we will add href hyperlink in the login.html and register.html file. Refer to the pictures shown below.

Registration of user by email confirmation in Django
hyperlink for register.html file
User authentication in Pyhton Django
hyperlink for login.html file

Now we have completed our HTML templates of login and register which we will render on the server.

Step 2: Run the server to view our application

We are going to run the development server to view our application on the server side. Run the command mentioned below in your terminal and go to the link generated.

Django user registration application
Login page for user login

Step 3: Generating a token for authentication

In this step, we will move to the next part of our application where we will generate tokens to authenticate our user registration through email.

For that, we will create a template success.html and token_send.html and in views.py we will add views for that also. Now create these files success.html and token_send.html in the templates folder where we have created our previous templates.

After creating templates we go to views.py and add views for these two files.

def register_attempt (request):
    return render(request , 'register.html')

def token_send (request):
    return render(request , 'token_send.html')

def success (request):
    return render(request , 'success.html')

Along with this, we need to register their URLs also. So, go to urls.py of the accounts app and follow the code mentioned below.

urlpatterns = [
    .

    .
    .
    path('token' , token_send , name='token_send'),
    path('success' , success, name ='success')
]

Now get back to our templates and follow the below html code for the structure of token_send.html and success.html.

#success.html
{% extends "base.html" %}
    
    {% block content %}
    <div class="global-container">
        <div class="card login-form">
        <div class="card-body">
            <h3 class="card-title text-center">You have successfully registered as user </h3>
            <div class="card-text text-center">
                Please login 
                <a class= "btn btn-primary" href="{% url 'login_attempt' %}"></a>
               
            </div>
        </div>
    </div>
    </div>
#send_token.html
{% extends "base.html" %}
    
    {% block content %}
    <div class="global-container">
        <div class="card login-form">
        <div class="card-body">
            <h3 class="card-title text-center">We have sent you an email </h3>
            <div class="card-text text-center">
                Please check your email for login verification 

               
            </div>
        </div>
    </div>
    </div>

Creating models

Now we will move to the user model to see how we will send a confirmation email to a user after authentication. In Django there are two methods for authentication first is to overwrite the user or to use the relationship to extend the user field. We are going to use the second one. First, create models in models.py of our app.

Follow the below code for models.py.

from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User)
    auth_token = models.CharField(max_length=100)
    is_verified = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user.username

Make migrations

We have created models now to execute these changes we need to propagate the changes we have made in models into the database. Now to make migrations run the below commands in the terminal.

> python manage.py makemigrations
> python manage.py migrate

Read How to Register User with OTP Verification in Django

Step 4: Create a superuser

To view the data we need to go into the Django admin panel and for that, we need to create a superuser account to access the Django admin panel. Now follow the below command in the terminal to create a superuser.

> python manage.py createsuperuser

Creating posts in views.py

In this step, we are going to create a POST IN views.py file for our register page. We have also used the try-and-catch method so that it won’t ruin the user experience.

def register_attempt (request):
    if request.method == 'POST' :
        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('password')

        try:
            if User.objects.filter(username = username).first():
              messages.success(request,'Username is taken.')
              return redirect('/register')
        
            elif User.objects.filter(email = email).first():
              messages.success(request, 'Email is taken')
              return redirect('/register')
        
            user_obj = User.objects.create(username = username, email=email)
            user_obj.set_password(password)

            profile_obj = Profile.objects.create(user = user_obj , token = str(uuid.uuid4))
            profile_obj.save()

            return redirect('/token')

        except Exception as e:
            print(e)

        
    return render(request , 'register.html')

After this, we will add a field in the register.html page and also an alert message in our registration form with the help of the Django message field. So, just edit the code mentioned below in register.html

<h3 class="card-title text-center">Register for user account</h3>
            <div class="card-text">
                <form>
                        
                    {% if messages %}

                    
                        {% for message in messages %}
                        <div class="alert-info">
                            {{ message }}
                        </div>
                        {% endfor %}
                    
                    {% endif %}
            
                    <div class="form-group">
                        <label for="exampleInputEmail1">Username</label>
                        <input type="text" name="username" class="form-control form-control-sm" id="exampleInputEmail1" aria-describedby="emailHelp">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputEmail1">Email address</label>
                        <input type="email" name="email" class="form-control form-control-sm" id="exampleInputEmail1" aria-describedby="emailHelp">
                    </div>

Go to admin.py and add the code mentioned below.

from django.contrib import admin
from .models import *

admin.site.register(Profile)

Create a function send_mail, verify, and error in views.py

def verify(request , auth_token):
    try:
        profile_obj = Profile.objects.filter(auth_token = auth_token).first()
        if profile_obj:
            profile_obj.is_verified = True
            profile_obj.save()
            messages.success(request, 'You account is been verified')
            return redirect('/login')
        else:
            return redirect('/error')
    except Exception as e:
        print(e)


def error_page(request):
    return render(request, 'error.html')   


def send_mail_after_registration(email,token):
    subject = "Your account needs to be verified"
    message = f'Hi paste your link to verify your account http://127.0.0.1:8000/verify/{token}'
    email_from = settings.EMAIL_HOST_USER
    recipient_list = [email]
    send_mail(subject, message , email_from ,recipient_list)

In case we got an error we have to create an error.html file also to render the error page.

{% extends "base.html" %}
    
    {% block content %}

    <div class="global-container">
        <div class="card login-form">
        <div class="card-body">
            <h3 class="card-title text-center">Error</h3>
                
            </div>
        </div>
    </div>
    </div>

    {% endblock %}

Register these functions in urls.py.

urlpatterns = [
   .

   .
   .
   .
    path('success' , success, name ='success'),
    path('verify/<auth_token>' , verify ,name = "verify"),
    path('error' , error_page , name = "error")
]

Step 5: Setup Email backend

To access the SMTP settings of the email backend by which we will able to send email through our application. Register the following settings in the settings.py file.

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "your email account"
EMAIL_HOST_PASSWORD = "16-digit code generated by gmail in 2-factor authentication"

Run development server

Now we have completed the configuration required for our app now we will run the development server and test our app. After running the command python manage.py runserver open the http://127.0.0.1:8000/register

Django user authentication app from email
Registering user for authentication in the Django app

After registering you will see a success message for the account have been created.

Django user authentication app in Python
Success message for user registration

Now go to the Email account which you have registered in the registration form. You will get a link in your email that will redirect you to the login page with the message of successful account verification confirmation.

Django app user registration through email
User registration confirmed through the link

Conclusion

In this Python Django tutorial, We have successfully created a Django user registration app and also verified the registration through email, and also tested the working of our application.

We have also learned about the Smtp server settings and generating tokens for user authentication.

You may also like to read the following articles: