DEV Community

Skriptmonkey
Skriptmonkey

Posted on • Edited on

QR Code Gen - Creating the model

Okay, now that the holidays are over. Let's get back to it, shall we? My hope is to get these out on a more regular schedule. However, like during the holiday season, sometimes other obligations (family, work) take priority.

I'm just going to jump right in to creating the QR app and designing/testing our basic "starter" model.

Create the app

Creating the app is simple enough.

$ django-admin startapp qr
Enter fullscreen mode Exit fullscreen mode

Then open the config/settings.py file and add 'qr', to the end of the "INSTALLED_APPS" variable.
settings.py
Now that we have the "application" created, we can start thinking about content.

Location location location

We need to figure out where we're going to store the QR code images when they're generated. In a larger project we might consider storing the images on a CDN (content delivery network) for better distribution over geographically different locations. But this isn't a big project. This is a small project where I don't expect anyone to really use so I'm not going to worry about load times, yet.
What I will do, is create a 'media' folder at the base of the project and set the 'MEDIA_ROOT' variable to the new folder in the settings.py file.
MEDIA_ROOT
Note: I also had to add import os to the top of my settings file.

Also, quick tip: keep a separate terminal open with python manage.py runserver running. Whenever you save a change to a file it'll refresh the local web server and report any errors (like using the os module without importing it).

Create the model

This will be a simple model to start. All we want is a single line text input which we'll use to generate the QR code. We can add more QR code customization later.
So what fields do I need?

  1. a field to store the input text.
  2. a field to store the location of the generated image
  3. and a field for the creation date. I'm also adding in a couple of functions (stolen from the Django tutorial) to help later on. Here is what my qr/models.py file looks like so far.
import datetime
from django.db import models
from django.utils import timezone

class QRCode(models.Model):
    input_text = models.CharField(max_length=200)
    qr_code_img = models.ImageField(upload_to='qr_codes/')
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.input_text

    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <=self.pub_date <= now
Enter fullscreen mode Exit fullscreen mode

I also needed to install the pillow module using pip install pillow to use the ImageField field.

The Segno Package

Now that we have a model, I'd like to do something with it. As in, create some QR codes. To do that, I've decided to go with the Segno package. And... I'll be honest, I did about 10 seconds of searching and just picked something. Segno seems easy enough to use and looks like it has the features that I'd want in a QR code generating web app.
Installing Segno was straight forward:

(.venv)$ pip install segno
Enter fullscreen mode Exit fullscreen mode

Creating a QR code using Segno is also very easy.

import segno
qrcode = segno.make("test")
qrcode.save("test.png")
Enter fullscreen mode Exit fullscreen mode

This creates a "test" QR code and saves it as "test.png". Easy right?

You can find more info on the Segno package from the PyPi website.

Testing the model

Now let's test out the model using the Segno package. I'm taking another chapter out of the Django tutorial and using the Django shell to do our testing. But first, let's migrate our changes.

(.venv)$ ./manage.py makemigrations
Migrations for 'qr':
  qr/migrations/0001_initial.py
    + Create model QRCode
Enter fullscreen mode Exit fullscreen mode
(.venv)$ ./manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, qr, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying qr.0001_initial... OK
  Applying sessions.0001_initial... OK
Enter fullscreen mode Exit fullscreen mode

Now, let's enter into the shell to play around with our new model.

(.venv)$ ./manage.py shell
7 objects imported automatically (use -v 2 for details).

Python 3.14.2 (main, Dec  5 2025, 00:00:00) [GCC 15.2.1 20251111 (Red Hat 15.2.1-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import segno # import segno
>>> import os
>>> from django.utils import timezone # import django timezone
>>> QRCode.objects.all() # show that nothing has been done, yet.
<QuerySet []>
Enter fullscreen mode Exit fullscreen mode

Everything is setup, let's create a new QRCode object with some test input text. Then we'll use the new object's input_text to create the QR code and use the object's ID for the naming.

>>> qrcode = QRCode(input_text="This is a test", pub_date=timezone.now())
>>> qrcode.save()
>>> qrcode.id
1
>>> qrcode.qr_code_img = f"{qrcode.id}.png"
>>> qrcode.save()
>>> from config.settings import MEDIA_ROOT
>>> qr_code_path = os.path.join(MEDIA_ROOT, 'qr_codes', f"{qrcode.id}.png")
>>> qr = segno.make_qr(qrcode.input_text)
>>> qr.save(qr_code_path, scale=4)
Enter fullscreen mode Exit fullscreen mode

And now we should have a PNG file saved at media/qr_codes/1.png.
PNG Image created
To be honest, this last part took a lot longer than expected. I kept running into a FileNotFoundError when attempting to create the QR code image. This was resolved by creating the qr_code_path variable with the full path to the "1.png" file location, which involved needing to import the MEDIA_ROOT variable from config.settings.

Next up, I'll work on creating the templates for the input form and the QR code results page, then I'll work on creating the views later.

To some of you more experienced Django developers, some tips and tricks are always appreciated in the comments. Especially if it makes something that I've done in the post easier to accomplish.

Top comments (0)