NOTE: This is Part 1 of a multi-part series.

Part 2 is here.

In this post, we're going to know how to code modules in Python Django to use the Sparrow SMS API integration to verify a Nepali phone number (NTC/ Ncell) using an API as a service server-generated OTP code. This is a work in production example of an API as a service backend web app built around Django and Django REST framework that allows clients like mobile apps or React.js/ Vue.js enabled frontend interfaces to integrate a phone number verification using Sparrow SMS service gateway. In addition, this feature could be used as a sign in or sign up wall during user authentication.

To follow this post ahead, you will need:

Google SMS Retriever API
Source: Google Developers Guides

Assumed we have installed the requirements and started running an instance of a Django main project successfully, we can start by creating a new Django app using:

$ python manage.py startapp myappname

Creating a Django App from Terminal

that will create a directory structure as:

myappname/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

Default Django App Directory Listing

Sticking to the dev conventions, we will add more python files to the app later such as urls.py, serializers.py etc.

Step 1 — Defining database layout in models.py

The first step is to add some basic imports needed in our models.py file. MinLengthValidator and RegexValidator are the built-in validator classes from django.core module that checks the minimum length of a value and performs re.search() by a regex validation respectively. Next up we have models which is the most common and important db import. Finally the AbstractUser module allows us to customize the default user groups and auth permissions that comes battery included in django.contrib.

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.core.validators import MinLengthValidator, RegexValidator

Imports in models.py

class AccountUser(AbstractUser):

# other very important account user fields here

phone_regex = RegexValidator(regex=r'^98\d{8}$', message="Only 10 digits NTC or NCELL numbers allowed.")
phone_number = models.CharField(validators=[phone_regex], max_length=10, null=True, unique=True)
phone_verified = models.BooleanField(default=False)

Phone model attributes inside AccountUser

Here AccountUser is a custom account user model class that entails custom user model attributes like username, first_name, last_name etc. The custom class AccountUser subclasses in-built AbstractUser from django.contrib.auth.models from the imports section above.

AbstractUser provides the full implementation of the default User as an abstract model. - Django 3.2
class PhoneOtp(models.Model):
    phone_regex = RegexValidator(regex=r'^98\d{8}$', message="Only 10 digits NTC or NCELL numbers allowed.")
    phone_number = models.CharField(validators=[phone_regex], max_length=10, null=True, unique=True)
    validated = models.BooleanField(default=False, help_text="Ensure Mobile Verified Badge")
    otp_code = models.CharField(max_length=6, blank=True, null=True)
    otp_count = models.PositiveSmallIntegerField(default=0, help_text='Count of OTP sent.')

    def __str__(self):
        return self.otp_code + ' is the otp for ' + self.phone_number

A parent class in models.py for phone numbers database

Next is the class PhoneOtp that has a custom regex validator starting in line 2. If you look closely the regex only allows phone numbers that start with 98 plus any 8 digits afterwards; a total of 10 digit phone number 9812345678. But there are phone numbers in Nepal that start with 97 too. So you just need to change the regex as per your needs on phone_regex line 2.

phone_number will hold the 10 digit phone number and validate against the phone_regex rules specified above it; added to it you have other arguments like max_length null and unique to meddle in the database properties.

max_length allows you to set a maximum length of phone number digits including white spaces.
null specifies whether the phone number is allowed to be saved as a void in the database or not.
unique specifies the phone number to be unique in the database once saved unless popped off.

validated is another important model attribute that will store a boolean value; either a True or a False. This is where we set the verification badge status after the users have successfully verified their phone numbers. Each phone number entry in the database are set False 0 by default until the user verifies the phone number in which case the entry is updated to True 1. And in turn, the frontend UI developers can code the appropriate to denote the phone number as verified, checked etc.

otp_code will hold the 6 digits randomly generated number by the generate_otp function in the views.py file which in turn will act as the 6 digits One Time Passwords sent to the user's phone numbers by the Sparrow SMS API gateway.

otp_count will hold the integer values of the number of times the OTP is sent to a phone number by the server. This data will be useful to limit the unwanted retries by users for OTP to request or overload the SMS gateway within API level access.

Activating our AccountUser and PhoneOtp models from Terminal.

python manage.py makemigrations myappname

Save changes in models.py

python manage.py migrate myappname

Apply saved changes in models.py


I edit and update this article timely for corrections and improvements. Thank you for reading!