How to Deploy a Python Django Application using PlanetScale and Koyeb Serverless Platform

Introduction

Django is a popular and powerful framework for Python application developers. Django comes with many features like authentication, content administration, an Object-Relational Mapper (ORM), and much more.
Django supports various relational databases including MySQL which makes it possible to run a Django application using the PlanetScale database serverless platform without having to perform any changes in your application.

In this guide, we will create a Django application, configure our project to use a PlanetScale database, and deploy the application on the Koyeb Serverless Platform using git-driven deployment.

Using Koyeb git-driven deployment, your Koyeb application is linked to your GitHub repository and each time changes are pushed to your repository, your application is being redeployed automatically by Koyeb.

At the end of this guide, you will have a working Django application running on Koyeb.

Requirements

To successfully deploy a Django application on Koyeb, you need:

  • Python installed on your machine
  • A Koyeb account to deploy and run the Django application
  • A PlanetScale account to run the database our application will use
  • A GitHub account to store your application code and deploy your application on Koyeb via GitHub

Steps

To complete this guide to have a Django application running on Koyeb, you need to follow these steps:

Create a virtual environment

Before creating the Django application, we will create a virtual environment also known as a virtualenv. Virtual environments allow you
to create an isolated Python environment to avoid interfering with the Python's system packages or other virtual environments.

To create a new virtual environment that we will use for our Django application, in your terminal run:

python3 -m venv ~/.venv/django-app

This command creates a new folder django-app in the ~/.venv directory. The virtualenv contains a copy of the Python interpreter, pip, the standard library, and various supporting files.

We can now activate the virtualenv we previously created by running:

source ~/.venv/django-app/bin/activate

Once the virtualenv is activated, the virtualenv python and pip executables are added into your shell’s PATH.

Create a new Django application

Let's start by creating a dedicated folder for our app and moving into it:

mkdir django-on-koyeb
cd django-on-koyeb

Before creating our Django application, we need to install:

  • django, to install the Django framework and libraries
  • dj-database-url, a Django utility that allows to parse DATABASE_URL.
  • gunicorn, a pure-Python HTTP server for WSGI applications that can run multiple Python concurrent processes
  • mysqlclient, the librairies to use MySQL or in our case Planetscale

mysqlclient requires system librairies, please check
https://pypi.org/project/mysqlclient/ for detailled instructions

In your terminal, execute the following commands to install the packages locally and save
these dependencies.

pip install django gunicorn dj_database_url mysqlclient
pip freeze > requirements.txt

Once the previous step is completed, you can create the Django application in
our local directory by running:

django-admin startproject django_on_koyeb ./

This command creates a django_on_koyeb directory in your current directory containing the following files:

├── django_on_koyeb
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

Prepare the Django application for production

Next, we will edit the settings.py file as we need to customize settings
related to security and performance for
our development and production environment.

Open the settings.py using your favorite editor, here nano:

nano django_on_koyeb/settings.py

We will edit the settings.py file to load some important settings of our application using environment variables.
To access and read environment variables, we need to import the os module.

+import os
from pathlib import Path

Django also requires a SECRET_KEY. This key is used to provide cryptographic signing and should be set to a unique, unpredictable value.
By default, we will want to generate a random secret key when nothing is passed as an environment variable, i.e. when you are running in development mode.

To generate a random secret key, we will need to import from django.core.management.utils import get_random_secret_key:

import os
+from django.core.management.utils import get_random_secret_key
from pathlib import Path

Search for the SECRET_KEY = ... line in the settings.py file and replace it as below:

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', get_random_secret_key())

Now, when the DJANGO_SECRET_KEY environment variable is set, our application will use it. If no value is provided, the get_random_secret_key() function is called and will return a random secret key.

By default, the Django application runs in DEBUG. When deploying the application in production, for security and performance purposes DEBUG mode needs to be disabled. We will change the default value to disable DEBUG until it is explicitly enabled via the environment variable DJANGO_DEBUG=True.

DEBUG = os.environ.get('DJANGO_DEBUG', 'False') == 'True'

Next, update the ALLOWED_HOSTS directive to read the DJANGO_ALLOWED_HOSTS from the environment. ALLOWED_HOSTS is required to contain the list of strings representing the host/domain names that the Django application can serve.

ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(",")

Last, go to the bottom of the file and add the following directive below STATIC_URL:

STATIC_URL = '/static/'
+STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")

This setting is used to set the directory from which we want to serve static files.
The first part of the Django configuration is done, we can move to the next step and configure Django to use a PlanetScale database.

Configure Django to use a PlanetScale database

To use a PlanetScale database in our Django application, create a new database
from the PlanetScale control panel or using the
CLI running:

pscale database create django-on-koyeb

Once the database is created, create a new database password for the main branch. On the PlanetScale control panel, click the Connect button and new password to generate a user and password to connect the database.
You can also perform this action using the PlanetScale CLI by running:

pscale password create django-on-koyeb main production-password

Keep these credentials in a safe place, we will need them when deploying our application on Koyeb.

On PlanetScale, the main database's schema is immutable and all changes must occur on a development branch. As we will need to perform a migration propagate our models into our PlanetScale database,
we need to create a new branch.

On the PlanetScale control panel, click the New branch button and name the branch migration. You can also perform this operation using the PlanetScale CLI running:

pscale branch create django-on-koyeb migration

Once the branch is created, create a new database password to access the branch. On the PlanetScale control panel, click the Connect button and new password to generate a user and password to connect the database.
You can also perform this action using the PlanetScale CLI by running:

pscale password create django-on-koyeb migration migration-branch-password

As PlanetScale uses Vitess behind the scenes, we need to use a custom database engine to make our Django application work with Vitess.
To retrieve the Vitess custom engine, clone the Vitess repository and copy the custom_db_backends directory in your Django application root folder:

git clone https://github.com/vitessio/vitess.git ~/vitess
cp -r ~/vitess/support/django/custom_db_backends ./

Next, open the Django application settings.py:

nano django_on_koyeb/settings.py

By default, Django is using an SQLite database, we need to edit the
settings.py to use a Vitess database and retrieve the configuration via the DJANGO_DATABASE_URL environment variable.
If the DJANGO_DATABASE_URL is not set, the application will raise the exception DJANGO_DATABASE_URL environment variable not defined when starting.
In the settings.py replace the following part:

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': BASE_DIR / 'db.sqlite3',
#     }
# }
if os.getenv("DJANGO_DATABASE_URL", None) is None:
    raise Exception("DJANGO_DATABASE_URL environment variable not defined")

DB_PARAMS = dj_database_url.parse(os.environ.get("DJANGO_DATABASE_URL"))
DB_PARAMS["ENGINE"] = "custom_db_backends.vitess"
DATABASES = {
    "default": DB_PARAMS,
}

Let's not forget to import the dj_database_url module we're using:

import os
from django.core.management.utils import get_random_secret_key
+import dj_database_url
from pathlib import Path

You can now save and close the settings.py. Let's run Django migration to propagate the application models to the PlanetScale database. In the terminal run the following command:

DJANGO_DATABASE_URL=mysql://PS_USERNAME:PS_PASSWORD@PS_HOST:3306 python manage.py migrate

Replace the PS_USERNAME, PS_PASSWORD, PS_HOST values with the PlanetScale values you generated for the migration branch.

Then on the PlanetScale control panel, create a new Deploy request to propagate the schema changes performed on the migration branch to the production branch main and deploy it. You can also perform this operation using the PlanetScale CLI by running:

pscale deploy-request create django-on-koyeb migration
pscale deploy-request deploy django-on-koyeb 1

The application is now configured and ready to be deployed on Koyeb.

Deploy the Django application on Koyeb

As the Django application will be deployed on Koyeb using Git, we need to initialize a new git directory for our Django project.
In your terminal run:

git init

To keep only necessary files in our repository, we will add a .gitignore file to exclude undesired files.

curl https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore > .gitignore

Then, execute the following command to add files to commit to your repository and commit the changes

git add .
git commit -m "Django app initial commit"

Open a new tab in your browser and go to GitHub. Create a new repository named django-on-koyeb and click the Create repository button.
Then, go back to your terminal and add GitHub as a remote repository by running:

git remote add origin [email protected]:YOUR_GITHUB_USERNAME/django-on-koyeb.git

Rename the repository default branch to main executing:

git branch -M main

Last, push your changes to the GitHub repository by running:

git push -u origin main

Everything is now ready to deploy the Django application on Koyeb.

Go to the Koyeb control panel and click the Create App button.
Choose GitHub as a deployment method and choose the repository you previously created in the list and set main as the branch value.

Override the default Run command with the following value to get the application to run properly: gunicorn --worker-tmp-dir /dev/shm django_on_koyeb.wsgi

Then, in the Ports section change the default port from 80 to 8000 which is the default port our application is listening to.

In the Environment variables section:

  1. Add an environment variable of type Secret with DJANGO_DATABASE_URL as the value and in the value section click Create Secret and name your Secret django-db-url and mysql://PS_USERNAME:PS_PASSWORD@PS_HOST:3306 as value. Take care to replace PS_USERNAME, PS_PASSWORD, and PS_HOST with the PlanetScale password information you created for your main production branch.
  2. Create a plaintext environment variable with the name DJANGO_DEBUG and value set to True. We need this to validate our application is running properly as it doesn't contain any routes at the moment.
  3. Create a plaintext environment variable with the name DJANGO_ALLOWED_HOSTS and value set to django-on-koyeb-<KOYEB-ORG>.koyeb.app

Give your App a name, for instance django-on-koyeb and click the Create App button.

Your application is now being built and deployed on the Koyeb serverless platform. Within a few minutes, you will be able to access your application by clicking your App URL: https://django-on-koyeb-<KOYEB-ORG>.koyeb.app.

Conclusion

In this guide, we explained how to deploy a Django application on the Koyeb serverless platform with PlanetScale as the database backend for our application.
By deploying on Koyeb, your Django application is secured with native TLS encryption and benefits from all the Koyeb serverless features including autoscaling, auto-healing, and a high-performance edge network.

Thanks to the git-driven deployment feature offered by Koyeb, each time you push new modifications to your GitHub repository, a new deployment of your application occurs automatically.
This allows you to focus on your application code while Koyeb takes care of building, deploying your application, and ensure your service is always up and running.

If you have any questions or suggestions to improve this guide,
feel free to reach out to us on Slack.

14