Implementing WhatsApp Notifications with Templates in Django

March 11, 2021
Written by
Jekayinoluwa Olabemiwo
Contributor
Opinions expressed by Twilio contributors are their own

Implementing WhatsApp Notifications with Templates in Django

The Twilio WhatsApp API helps your application connect with your users through WhatsApp. Django is a Python framework used for the rapid development of web applications. It is free and open-source, with lots of features so you don't have to reinvent the wheel. It powers web services like Instagram and Spotify.

In this tutorial, we will implement a Django application that sends WhatsApp notifications to users. Below you can see an example.

 

project demo

Tutorial requirements

Setup the Django project

We need to set up the Django application, which will contain the logic for sending WhatsApp messages. Let us first install virtualenv and create a virtual environment for our project.

Install virtualenv with pip, the Python package manager:

python -m pip install --user virtualenv

Create a folder for our project and navigate into it:

mkdir whatsapp-templates
cd whatsapp-templates

Then, create a virtual environment for our project with virtualenv as follows:

virtualenv env

If you are using a Unix or MacOS computer, you can activate the virtual environment with the following command:

source env/bin/activate

If you are using a Windows computer, the virtual environment activation is:

env\Scripts\activate

With the virtual environment activated, install the packages needed for this project with:

pip install django twilio python-decouple

Now start a new Django project called notifications with the django-admin utility:

django-admin startproject notifications .

Then create a new application in the Django project, which will host the WhatsApp messaging feature. We will use the manage.py script provided by Django for administrative functions to create an application called core.

python manage.py startapp core
python manage.py migrate

Navigate to the settings.py in the notifications subdirectory and add core to the list of INSTALLED_APPS.

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

Django has a built-in local development server with which we can test our application with. Start the development server with the following command:

python manage.py runserver

The console output should look like this:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
March 03, 2021 - 14:12:25
Django version 3.1.7, using settings 'notifications.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-C.

Setup the Twilio sandbox for WhatsApp

To send messages with WhatsApp in production, WhatsApp has to formally approve your account. To simplify the development of WhatsApp applications, Twilio provides us with the Twilio Sandbox for WhatsApp. You can activate the sandbox in the WhatsApp section of the Twilio Console. You will need to agree to the terms and conditions before you can activate your sandbox environment.

Once you enter the sandbox activation page, you will be provided with a specific two-word join code that you need to send to the given sandbox number. The screen should be like this:

Twilio sandbox for WhatsApp

Send the code to the WhatsApp sandbox number using WhatsApp on your smartphone to establish a connection with your WhatsApp account. If you have done that, you should get a Message Received feedback on the screen as shown below:

Sandbox connected to phone

Prepare the Django Settings for the Project

Create a .env file in the project root directory to keep the Twilio credentials that the application will use to authenticate. Add them like this:

TWILIO_ACCOUNT_SID=************
TWILIO_AUTH_TOKEN=************

You can find the values for the Twilio Account SID and Auth Token that apply to your Twilio account in the Console. Save the file after adding the two variables.

Next, open the settings.py file from the notifications subdirectory in your editor. At the top of the file, add an import for the config module of python-decouple:

from decouple import config

Then at the bottom of the file, add two variables that match the Twilio credentials stored in the .env file:

TWILIO_ACCOUNT_SID = config('TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN = config('TWILIO_AUTH_TOKEN')

Choosing a WhatsApp message template

As a measure in preventing spam, WhatsApp requires that all notifications sent to users are based on a pre-approved template.  The approved categories are listed here, WhatsApp notification categories. To submit a Message Template for Approval, you need to get your WhatsApp account approved for production. Then, head to the WhatsApp message section of the Twilio console and submit your template for review.

Fortunately, the Twilio WhatsApp sandbox includes 3 approved message templates that are available for testing purposes. You can see them below:

  • Your appointment is coming up on {{1}} at {{2}}
  • Your {{1}} order of {{2}} has shipped and should be delivered on {{3}}. Details: {{4}}
  • Your {{1}} code is {{2}}

The templates have placeholders such as {{1}}, {{2}}, etc. where dynamic data can be inserted. In this tutorial we are going to use the order notification template.

If you are interested in learning more about WhatsApp notification templates and the approval process, see Creating message templates and submitting them for approval in the documentation.

Create a Django view to send WhatsApp messages

We need a Django view to hold the logic of our application. The view will accept the user’s WhatsApp number in a web form, and also control the sending of the WhatsApp notifications with the pre-approved message template when the form is submitted by the user.

Open the views.py file from the core application directory on your editor. Replace the content of this file with the following imports:

from twilio.rest import Client
from notifications.settings import TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN
from django.http import HttpResponse
from django.shortcuts import render

In the above code, we imported the Twilio Client class to be able to send messages through the Twilio API for WhatsApp. We also imported the TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN variables created earlier from the settings.py file. The HttpResponse class from Django will be used to return HTTP responses to clients, and the render function will render the Django HTML template.

Next, create a dictionary to hold example order details that will be sent out in the notification. In a real application this data will be retrieved from a database instead of being hardcoded.

order_details = {
    'amount': '5kg',
    'item': 'Tomatoes',
    'date_of_delivery': '03/04/2021',
    'address': 'No 1, Ciroma Chukwuma Adekunle Street, Ikeja, Lagos'
}

Add a view function called send_notification at the bottom of views.py:

def send_notification(request):
    client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)

    if request.method == 'POST':
        user_whatsapp_number = request.POST['user_number']

        message = client.messages.create(
            from_='whatsapp:+14155238886',
            body='Your {} order of {} has shipped and should be delivered on {}. Details: {}'.format(
                order_details['amount'], order_details['item'], order_details['date_of_delivery'],
                order_details['address']),
            to='whatsapp:+{}'.format(user_whatsapp_number)
        )

        print(user_whatsapp_number)
        print(message.sid)
        return HttpResponse('Great! Expect a message...')

    return render(request, 'phone.html')

The view function above handles GET and POST requests. When a GET request is received, it renders a web form for the user to supply their WhatsApp number. The form is rendered via a Django template ‘phone.html’ that we will create in the next section.

When the user submits the web form, a POST request will be received by the server. In this case the WhatsApp phone number of the user is retrieved from the form data in request.POST, and then a WhatsApp message is sent from the Twilio WhatsApp sandbox number to the user’s WhatsApp number.

Note how the body of the message conforms to the pre-approved order notification template, with the example order details inserted in the placeholder positions. The message will not be sent unless it matches one of the approved templates.

The from_ argument must be given with the format whatsapp:+xxxxxxxxxxx' and the number must match the sandbox number that was assigned to your sandbox.

Adding a Django HTML template

Now, we will create a Django template that will render the web form to the user. Create a templates subdirectory inside the core application. The directory structure should be as follows:

core/
  └──  templates/
        ├── base.html 
        └── phone.html

The base.html will contain the HTML structure of the website. The phone.html template will render the user input form and will inherit the general page layout from base.html.

Add the following code to the base.html file:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <div id="content">
        {% block content %}
        {% endblock %}
    </div>
</body>
</html>

Now, open the phone.html file and add the following code:

{% extends "base.html" %}
{% block title %}Customer WhatsApp Notification{% endblock %}

{% block content %}
    <h1>Submit WhatsApp Contact</h1>

    <form action="/" method="post">
        {% csrf_token %}
        <label for="your_name">Your WhatsApp number: </label> 
        <input id="user_number" type="text" name="user_number" >
        <input type="submit" value="Submit">
    </form>
{% endblock %}

This template file defines the form form with an action that sends POST requests to the / URL. It contains a labeled input element to accept the WhatsApp number from the user and a submit button for the user to submit the form. It extends the base.html file which structures the web page.

Save the two template files before continuing on to the next step.

Adding a URL pattern for the Django view

Now, let’s configure a URL for the view that we created to send WhatsApp messages. Navigate to the urls.py file in the notifications directory and open it. Then add a path to the list of urlpatterns:

from core.views import send_notification  # ← add this import

urlpatterns = [
    ...
    path('', send_notification),   # ← add this path definition
]

In the above code, we added an import statement linked to the send_notification view in the core application. Then, we attached the root URL of the application to this view.

Save the modified file and run the Django development server on the console:

python manage.py runserver

Then, navigate to http://127.0.0.1:8000/ in your browser. The webpage rendered should look like the following:

application web form

Input your WhatsApp number and click the submit button. You should get a response as this:

form response

The code would run and you will get a WhatsApp message that says, "Your 5kg order of Tomatoes has shipped and should be delivered on 03/04/2021. Details: No 1, Ciroma Chukwuma Adekunle Street, Ikeja, Lagos". Then, the SID of the message sent will be shown in the terminal. The screenshot below shows how the message would look like on WhatsApp.

project demo

Next Steps

In this tutorial, we have learned how to create WhatsApp message templates, submit them for approval and implement them in Django projects. You may try advancing your knowledge of the WhatsApp API by learning how to store data in your Twilio WhatsApp API projects with this tutorial, How to Connect a Twilio WhatsApp Python Project to SQLite3.

Let me know if this tutorial has been helpful by tweeting at me. I would appreciate your ideas and suggestions too.

Jekayinoluwa Olabemiwo is a software craftsman who enjoys applying multidisciplinary approaches to solving problems. He can be reached on Twitter or LinkedIn.