How I Built a QR Code Generator in Django Web Application

A quick response code, otherwise known as a QR code, is a 2D barcode with white background and a black pattern all over it. It is capable of storing anything, whether it is text, images, or links, or whether they are extremely large or relatively small.

QR codes are becoming important and more commonly used in businesses as they provide a convenient way to access something quickly simply by scanning with a mobile device. With a QR code, you can send someone a website link, personal messages, images, video, or even Bitcoin in a much cooler way.

Won’t it be nice to learn how to generate QR codes so you can have fun playing with it, probably to send love messages to your bestie or to use it for business purposes? Python has got us covered with several libraries that make that possible.

By using such libraries, the heavy lifting has been done for us. All we need to do is to integrate it into our application. What better place to generate a QR code than in a Django web application? That is precisely what we are going to learn in this tutorial.

Setting up Django

To get started, we have to install Django and its dependencies in our Linux system. As always, we create and change into a new folder for this project.

mkdir && cd qrcode

Create and activate a virtual environment.

python3 -m venv .venv
. .venv/bin/activate

You can also use the source command instead of a dot. We now install Django, pillow, and qrcode Python modules.

pip install django qrcode pillow tzdata

Django is for creating the web application, qrcode is for generating QR codes, and pillow will be used to display the QR code image. But tzdata is just there to avoid Django throwing errors regarding UTC timezones.

Create a requirements.txt file for the module versions.

pip freeze > requirements.txt

Create a Django project and Django app in your current folder.

django-admin startproject project .
python3 manage.py startapp qr_code

Add the created app under the INSTALLED SECTION of the settings.py file.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # custom app
    'qr_code',
]

Run the migration command to apply the unapplied migrations for the app.

python3 manage.py migrate

Start the local server to ensure everything is working as expected.

python3 manage.py runserver

A congratulatory message will be shown to you once you start the local server. This shows that the installation was successful.

Creating and registering new folders

We are going to create three folders inside the current directory. Close the local server with Control + C.

mkdir media templates static

Django by convention saves all images in the media folder. Since the QR code generated is an image, we create a media folder to save all the generated QR code images. Then we register the folder in the settings.py file. Don’t forget to import the os module.

MEDIA_URL = 'media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

BASE_DIR means the current directory. When Django wants to serve images to template files, it will search the current directory for a media folder.

The templates folder is where we will keep all HTML files.

Let’s also register it in the TEMPLATES section of the settings.py file.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], #add these
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Lastly, the static folder. This is where we will keep all static files such as CSS. As usual, we register it in the settings.py file just under STATIC_URL. A one-line addition.

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

As we are not working with models, we move over to views.

The view() function

The view() function will contain the logic to generate the QR code.

from django.shortcuts import render
from qrcode import make
from django.conf import settings
from time import time



def generate_QR_code(request):
    if request.method == 'POST':
        data = request.POST['text']
        img = make(data)
        img_name = f'{str(time())}.png'
        img.save(settings.MEDIA_ROOT + '/' + img_name)
        context = {
            'img_name': img_name
        }
        return render(request, 'index.html', context)
    return render(request, 'index.html')

The view() function checks if the request method is POST. This means our template file must contain a form with its input tag attribute set to text to enable Django to retrieve the data input by the user.

Once that is done, all we need is the make class from the qrcode module to generate a QR code for any text written. We use the time() method to generate a random number that will serve as name for each QR code generated. Then, we save it in the media folder through the project’s settings:

img.save(settings.MEDIA_ROOT + '/' + img_name)
context = {
    'img_name': img_name
}
return render(request, 'index.html', context)

So, instead of rendering img, we render img_name. We are, in effect, displaying an image file that has been generated and saved in the media folder.

The Templates and Static files

Here is the index.html file saved in the templates folder:

{% load static %}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, intial-scale=1.0">
    <link rel="stylesheet" href="{% static 'styles.css' %}">
    </head>
  <body>
    <main>
        <h1>
          Django QR Code Generator
        </h1>
        <form method="post">
            {% csrf_token %}
            <input type="text" name="text" id="data" placeholder="write something or enter url">
            <button>Generate</button>
        </form>

        <div class="qr-img">
            {% if img_name %}
                <img src="/media/{{ img_name }}" alt="qr code">
            {% endif %}
        </div>
    </main>
  </body>
</html>

And here is the static file inside the static folder (styles.css) that contains CSS for styling the web page:

        *{
            background: gold;
            box-sizing: border-box;
            font-family: sans-serif;
        }
        main{
            width: 100%;
            max-width: 600px;
            margin: 0 auto;
        }

        input{
            width: 100%;
            padding: 10px;
            margin-bottom: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }

        button{
            width: 100%;
            max-width: 200px;
            padding: 10px;
            margin-bottom: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            background-color: #eee;

        }

        button:hover{
            background-color: #ddd;
        }

        .qr-img{
            width: 100%;
            max-width: 300px;
            margin: 0 auto;
        }
        .qr-img img{
            width: 100%;
        }

In the index.html file, we load the static files, and using Django Template language, we link the styles.css to the template file. Every form must include csrf_token for security. Notice the name attribute is set to text in the input. This way Django can retrieve the data.

Using Django if statement ensures that the QR code will be generated and displayed on the web page upon request. Notice how using Django template language in the {...} block makes it possible to dynamically write to the web page.

The URLs

Let us now configure the URLs starting with the project-level URLs. Go to URLs.py file in the project folder.

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

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

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Because we include the app URLs, we will also configure the URLs. The empty string tells Django to display the template files on the homepage. We also connect the media files to the URL. Finally, the app-level URLs.

Create a URLs.py file in the qr_code folder.

from django.urls import path
from .views import generate_QR_code


urlpatterns = [
    path('', generate_QR_code, name='home'),
]

That’s it. We are done. fire the local server, let’s see what we have done:

If you scan the QR code, you will see the above statement. If you input a link to a website, it will automatically direct you to it. Have fun playing with the application.

Conclusion

We have seen how to generate a QR code in a Django web application. That must have been a bit of pain. But it’s one of the processes you must undergo to master Django for web development.

Why not give it a try using the Flask framework! It will be a nice project to do. I may try to do so in upcoming projects. The full code is found on my GitHub page.

A word of caution: Be careful while scanning QR codes. Hackers can use it to direct you to a website automatically capturing your data or your phone’s geolocation without your knowledge. Use with discretion. Thank you.

πŸ’‘ Recommended: How I Created a Currency Prediction App Using Streamlit