How to Register User with OTP Verification in Django

In this Python tutorial, we will learn “how to register user with OTP verification in Django”. we will build a project ‘otpverification’ that takes user information and send the OTP then verifies the OTP entered by the user to register the user in the database.

To create the project follow the below steps:

Open a command prompt and navigate to the directory where you want to create your Django Project.

mkdir django_otpverify

Change the directory to django_otpverify and create a virtual environment.

python -m venv env

Activate the virtual environment ‘env’ using the below code.

env\Scripts\activate

Install the Django framework.

pip install django

Create a project named ‘otpverification’ using the below code.

django-admin startproject otpverification

Create an app named ‘account’ using the below code.

python manage.py startapp account

Run the below command to open the project in the visual studio.

code .
How to Register User with OTP Verification in Django Project Environment Setup
How to Register User with OTP Verification in Django Project Environment Setup

Now open the file ‘setting.py’ in the project folder named ‘otpverification` and the created app ‘account’ in the INSTALLED_APPS section as shown in the below picture.

INSTALLED_APPS = [
     . . . .,
    'account'
]
How to Register User with OTP Verification in Django Adding App to Setting File

Then run the below code into the terminal to create a database and its table that already exist in the Django project.

python manage.py migrate
How to Register User with OTP Verification in Django Setting Up Database
How to Register User with OTP Verification in Django Setting Up Database

After creating the ‘account’ app, open the file ‘account/models.py’ and define the new model ‘JobUser’.

from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from .managers import UserManager
from phonenumber_field.modelfields import PhoneNumberField

class JobUser(AbstractBaseUser):
    VERIFICATION_TYPE = [
        ('sms','SMS'),
    ]
    
    phone_number = PhoneNumberField(unique = True)
    verification_method = models.CharField(max_length=10,choices= VERIFICATION_TYPE)
    is_active = models.BooleanField(default= True)
    is_admin = models.BooleanField(default= False)
    is_staff = models.BooleanField(default= False)
    is_superuser = models.BooleanField(default=False)

    USERNAME_FIELD = "phone_number"
    objects = UserManager()
    
    def __str__(self):
        return str(self.phone_number)
    
    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(self, app_label):
        return self.is_admin
How to Register User with OTP Verification in Django JobUser Model
How to Register User with OTP Verification in Django JobUser Model

Register the model JobUser in the file named ‘account\admin.py’ using the below code.

from django.contrib import admin
from .models import JobUser

admin.site.register(JobUser)
How to Register User with OTP Verification in Django Register Model
How to Register User with OTP Verification in Django Register Model

After writing the above code, you need to install the package ‘pip install django-phonenumber-field’ and ‘pip install django-phonenumbers’ so run the below code in your terminal.

pip install django-phonenumber-field
pip install django-phonenumbers

Then create a manager named ‘UserManager’ for the JobUser by creating the new file at ‘account/managers.py’.

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


class UserManager(BaseUserManager):
    
    def create_user(self, phone_number, password = None, verification_method = 'sms',**extra_fields):
        if not phone_number:
            raise ValueError("The Phone Number field is required")
        
        user = self.model(phone_number = phone_number, verification_method = verification_method,**extra_fields)
        user.set_password(password)
        user.save(using = self._db)
        return user
    
    def create_superuser(self, phone_number, password = None, **extra_fields):
        
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        user = self.create_user(phone_number,password, verification_method='sms',**extra_fields)
        user.is_admin = True
        user.save(using=self._db)
        return user
How to Register User with OTP Verification in Django UserManager
How to Register User with OTP Verification in Django UserManager

Run the below command to create the table ‘JobUser’ in the database.

python manage.py makemigrations account
python manage.py migrate

Then create two forms named ‘UserRegistrationForm’ and ‘LoginForm’ in the new file named ‘account/forms.py’.

from django import forms
from .models import JobUser


class UserRegistrationForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)
    verification_method = forms.ChoiceField(
        choices=JobUser.VERIFICATION_TYPE,
        widget=forms.RadioSelect
    )
    

    class Meta:
        model = JobUser
        fields = ('phone_number', 'password', 'verification_method')

        
class UserLoginForm(forms.Form):
    phone_number = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)
How to Register User with OTP Verification in Django User Registration and Login Form
How to Register User with OTP Verification in Django User Registration and Login Form

Create a templates folder in the account app, within the templates folder make three new HTML files named ‘base.html’, ‘registration.html’, and ‘login.html’.

‘base.html’ file

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}User Phone OTP Verification{% endblock %}</title>
    <!-- Include necessary CSS files and stylesheets -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <style>
        /* Add custom styles here */
    </style>
</head>
<body>
    <!-- Navigation bar -->
    <nav class="navbar navbar-expand navbar-dark bg-dark">
        <a class="navbar-brand" href="#">User Phone OTP Verification</a>
        <ul class="navbar-nav ml-auto">
            <li class="nav-item">
                <a class="nav-link" href="{% url 'user_registration' %}">Register</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="{% url 'user_login' %}">Login</a>
            </li>
        </ul>
    </nav>

    <!-- Page content -->
    <div class="container mt-4">
        {% block content %}
        <!-- Content of each individual page will be inserted here -->
        {% endblock %}
    </div>

    <!-- Include necessary JS files and scripts -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    <script>
        // Add custom scripts here
    </script>
</body>
</html>
How to Register User with OTP Verification in Django Base Html File

Create a ‘registration.html’ to get the user information.

{% extends 'base.html' %}

{% block content %}
  <h2>User Registration</h2>
  {% if messages %}
    {% for message in messages %}
      <div class="alert alert-danger">{{ message }}</div>
    {% endfor %}
  {% endif %}
  
  <form method="post" action="{% url 'user_registration' %}">
    {% csrf_token %}
    {{ form.as_p }}
    
    {% if otp_required %}
      <div class="form-group">
        <label for="id_otp">OTP:</label>
        <input type="text" id="id_otp" name="otp" class="form-control" required>
      </div>
      <button type="submit" class="btn btn-primary">Verify OTP</button>
    {% else %}
      <button type="submit" class="btn btn-primary">Generate OTP</button>
    {% endif %}
  </form>
{% endblock %}
How to Register User with OTP Verification in Django Registration Html File
How to Register User with OTP Verification in Django Registration Html File

Create a ‘login.html’ to get the user login information.

{% extends 'base.html' %}

{% block content %}
  <h2>User Login</h2>
  {% if messages %}
    {% for message in messages %}
      <div class="alert alert-danger">{{ message }}</div>
    {% endfor %}
  {% endif %}
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" class="btn btn-primary">Login</button>
  </form>
{% endblock %}
How to Register User with OTP Verification in Django Login Html File
How to Register User with OTP Verification in Django Login Html File

For sending and receiving the sms on the phone, here we will use Twilio. So install the Twilio package in your project using the below code by running it in your terminal.

pip install twilio

After installing the Twilio package, create a view for the user registration, login, and OTP verification by following the below steps:

Open the file ‘views.py’ at the location ‘account/views.py’, and import the required libraries or modules.

from django.shortcuts import render
from django.shortcuts import render, redirect
from django.views import View
from .forms import UserRegistrationForm, UserLoginForm
from django.contrib import messages
import random
from twilio.rest import Client
from otpverification import settings
from django.contrib.auth import get_user_model

Create the view named ‘OTPVerificationView’ using the below code.

class OTPVerificationView(View):
    def post(self, request):
        submitted_otp = request.POST.get('otp')
        saved_otp = request.session.get('otp')
        password = request.session.get('password')
        
        if submitted_otp == saved_otp:
            messages.success(request, "OTP verification successful")
            phone_number = request.session.get('phone_number')
            User = get_user_model()
            user = User.objects.create(phone_number=phone_number)
            user.set_password(password)
            user.save()
            return redirect('user_login')
        else:
            messages.error(request, "Invalid OTP. Please try again.")
            return redirect('otp_verification')
How to Register User with OTP Verification in Django OTPVerificationView
How to Register User with OTP Verification in Django OTPVerificationView

Create the view named ‘UserRegistrationView’ using the below code.

class UserRegistrationView(View):
    def get(self, request):
        form = UserRegistrationForm()
        return render(request, 'registration.html', {'form': form, 'otp_required': False})

    def post(self, request):
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            phone_number = str(form.cleaned_data['phone_number'])
            verification_method = form.cleaned_data['verification_method']

            if 'otp' in request.POST:
                return OTPVerificationView.as_view()(request)
            else:
                password = form.cleaned_data['password']
                otp = generate_otp()

                if verification_method == 'sms':
                    send_sms_otp(phone_number, otp)

                request.session['otp'] = otp
                request.session['phone_number'] = phone_number
                request.session['password'] = password
                form.fields['password'].widget.attrs['value'] = password

                return render(request, 'registration.html', {'form': form, 'otp_required': True, 'password': password})

        return render(request, 'registration.html', {'form': form, 'otp_required': False})
How to Register User with OTP Verification in Django UserRegistrationView

Create a view named ‘UserLoginView’ using the below code.

class UserLoginView(View):
    def get(self, request):
        form = UserLoginForm()
        return render(request, 'login.html', {'form': form})
    
    
    def post(self, request):
        form = UserLoginForm(request.POST)
        if form.is_valid():
            messages.success(request,'Login SuccessFul')
            mobile_number = form.cleaned_data['phone_number']
            password = form.cleaned_data['password']
            otp = form.cleaned_data['otp']
            
        
        return render(request, 'login.html',{'form':form})
How to Register User with OTP Verification in Django UserLoginView
How to Register User with OTP Verification in Django UserLoginView

Also, create the two function named generate_otp()’ and send_sms_otp()’ that is used in the ‘UserRegistrationView’ for generating random OTP and sending SMS on the user’s phone respectively. Create these two functions at the bottom of the view.py file

def generate_otp():
    return str(random.randint(100000, 999999))

def send_sms_otp(phone_number, otp):
    client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
    message = client.messages.create(
        body=f'Your OTP is: {otp}',
        from_=settings.TWILIO_PHONE_NUMBER,
        to=phone_number
    )

Open the file ‘setting.py’ and add the following lines to set up your JobUser Model and Twilio sms service as shown in the below picture.

AUTH_USER_MODEL = 'account.JobUser'


TWILIO_ACCOUNT_SID = 'Enter the ACCOUNT_SID from the Twilio '
TWILIO_AUTH_TOKEN = 'Enter the AUTH_TOKEN from the Twilio'
TWILIO_PHONE_NUMBER = 'Specify the Phone Number from Twilio '

You can get the above information such as ACCOUNT_SID, AUTH_TOKEN, and PHONE_NUMBER from the Twilio console.

How to Register User with OTP Verification in Django Twilio Details

Open the file ‘urls.py’ of the project ‘otpverification’ and add the following URLs.

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('account.urls'))
]
How to Register User with OTP Verification in Django Adding URL For Project
How to Register User with OTP Verification in Django Adding URL For Project

Now open the file ‘urls.py’ of the app level ‘account’ and add the following URLs.

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

from .views import UserRegistrationView, UserLoginView, OTPVerificationView

urlpatterns = [
    path('register/', UserRegistrationView.as_view(), name='user_registration'),
    path('login/', UserLoginView.as_view(), name ='user_login'),
    path('verify-otp/', OTPVerificationView.as_view(), name='otp_verification'),
]
How to Register User with OTP Verification in Django Adding URL For App Level Account
How to Register User with OTP Verification in Django Adding URL For App Level Account

Now run the server or your project using the below command in the terminal.

python manage.py runserver
How to Register User with OTP Verification in Django Runserver
How to Register User with OTP Verification in Django Runserver

If you see something like shown in the above picture, then your project is working correctly. To test your project enter the URL in the browser ‘http://127.0.0.1:8000/register/’ and you will see the registration page for the user as shown in the below picture.

How to Register User with OTP Verification in Django User Registration Page
How to Register User with OTP Verification in Django User Registration Page

Enter the required details like Phone number, and password and choose the verification method as SMS, then click on the button Generate OTP. After this, you receive the OTP on your phone.

Now enter the received OTP and click on the button Verify OTP.

How to Register User with OTP Verification in Django Verifying OTP
How to Register User with OTP Verification in Django Verifying OTP

After verifying the OTP, you will be redirected to the login page where you see the message on the top ‘OTP verification successful’, if you enter the correct OTP otherwise you will see the error message ‘Invalid OTP. Please try again’.

How to Register User with OTP Verification in Django Verified OTP Successful
How to Register User with OTP Verification in Django Verified OTP Successful

Download the Complete OTP Verification Application

Conclusion

In this Python tutorial, we have learned how to register the user with OTP verification in Django, we learned how to use the Twilio sms service in our project and the logic to send, receive and verify the OTP.

You may also like to read