Contents

Deploy Wagtail/Django to Heroku with Github


Once you’ve created an awesome local website with wagtail or django framwork, you’ll want to make it pulic to everybody or somebody over the internet. There are dozens of hosting providers that actively support with django. I am not going to discuss pros and cons for different hosting vendors in this post. Heroku is the platform I choose for my little wagtail project so I’ll just focus on how to deploy wagtail project to heroku here.

A little bit different from heroku official django deployment guid, I am using github instead of heroku CLI for deployment. The reason for doing this is heroku CLI adds a new heroku remote repository named heroku on the heroku cloud. When you want to deploy your site, you push your changes to the heroku repository. I’d like to keep my code on github so I prefer to use github for deployment too.

Note
Wagtail is a framework build on top of django and keeps pretty much all configuration the same as django. I am using wagtail site in this post but the deployment steps applies to django sites too.

Create new wagtail/django project

Create virtual environment

Virtual environment is recommended for all python projects. So create an virtual environment with venv first: On windows:

1
2
python3 -m venv mysite\env
mysite\env\Scripts\activate.bat

On unix or mac:

1
2
python3 -m venv mysite/env
source mysite/env/bin/activate

Install wagtail

1
pip install wagtail

Generate starter site

1
2
cd mysite
wagtail start mysite mysite

Tip
First mysite is the project name and second mysite is the root directory for the project. If you already inside mysite folder, just type wagtail start mysite . instead.
Note
Django uses django-admin startproject instead of wagtail start for new project generation.

Getting wagtail site ready to deploy

Create github project

<username> needs to be replaced with your github username.

<repo-name> needs to be replaced with your own repo name.

Create a new repository on the command line

1
2
3
4
5
6
git init
git add README.md
git commit -m "Init commit"
git branch -M master
git remote add origin https://github.com/<username>/<repo-name>.git
git push -u origin master

Or push existing repository from the commmand line

1
2
3
git remote add origin https://github.com/<username>/<repo-name>.git
git branch -M master
git push -u origin master

Check critical settings

The default project created are configured for development. Many of the settings should be different for production, either for security or performance reasons.

The critical settings are:

  • DJANGO_SETTINGS_MODULE: This is used to specify which settings module to use. Default is development if not present.
  • DEBUG: This should be set as False in production. This stops debugu trace information from being displayed.
  • SECRET_KEY: This is a string for CSRF protection. It is hardcoded in default development settings module and can be pushed to source control, but that’s a risk for production. Best practice is keep it in a server only file or server environment variable and never push it to the internet including cource control.
  • DATABASE_URL: Default SQLite database is file based thus cannot be used on heroku(and not recommend to use on any other hosting vendor), because it would be deleted from eht ephemeral file system(simillar to docker file system) every time the applicaton restarts.
  • MIDDLEWARE: We need whitenoise to serve static files.
    Note
    Heroku automatically adds a postgresql database addon to your dyno and supplies database connection information to the web dyno using a configuration variable named DATABASE_URL.

We need to install additional packages for above chagnes:

1
2
3
pip install psycopg2
pip install django-toolbelt
pip install whitenoise

Then update DATABASES in base.py settings:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# base.py 

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'mysite',
    }
}

...

MIDDLEWARE = [
    ...
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',  # <-- Newly added
    ...
]

Update requirements file for installed python packages:

1
pip freeze > requirements.txt

Update production.py

Add following to production.py(production settings module):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from __future__ import absolute_import, unicode_literals
import os
import dj_database_url
DATABASES['default'] =  dj_database_url.config()
    
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# Allow all host headers
ALLOWED_HOSTS = ['*']

env = os.environ.copy()
SECRET_KEY = env['SECRET_KEY']
Note
from __future__ import absolute_import, unicode_literals line should be at the top of production.py file, before every other import.

Procfile and runtime

Procfile and runtime.txt are two files needed by heroku. They are just plain text files(without any extension) that specify how to create dyno and which version of python to use.

Create procfile file and copy the following text into it:

1
web: gunicorn locallibrary.wsgi --log-file -

Create runtime.txt file and copy the following text into it:

1
python-3.9.2

Runtime list for python can be found here: heroku python runtimes

Commit changes and push to remote

Create a .gitignore file if not exist. Add following to it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
*.pyc
*.bak
*.sqlite3
*.swp
.env
/env/
.DS_Store
/static/
/media/
.vscode

Use git add -A to add all files to git.

Use git status to check that all files about to commit are correct.

Now we are ready to roll, commit the files to the local repository:

1
git commit -m "First version of application"

After that, push all previous changes to the github remote repository:

1
git push origin master
Note
master is the remote repository branch name, yours may be different.

Connect heroku with github

Create heroku app

In your heroku dashboard create a new app: /assets/wagtail-heroku-deployment.assets/createapp.png

Add github connection

Then go to Deploy tab of newly created app, add github connection to it: /assets/wagtail-heroku-deployment.assets/connectgithub.png

Add environment variable

Follow the instructions to add existing github project to heroku. Two more environment variables need to be added to our app. Go to settings tab and expand Config Vars: /assets/wagtail-heroku-deployment.assets/configvars.png

Add DJANGO_SETTINGS_MODULE and SECRET_KEY: /assets/wagtail-heroku-deployment.assets/newvars.png

Deploy

Now go to Deploy tab and scroll all the way down, click Deploy Branch button for deployment. /assets/wagtail-heroku-deployment.assets/firstdeploy.png

If everything works as expected, the app is now running on the heroku cloud, but it won’t working properly because we haven’t set the database yet. Like the local development, we need to perform database migration and creating superuser for this app.

/assets/wagtail-heroku-deployment.assets/initrun.png

Run python manage.py migrate: /assets/wagtail-heroku-deployment.assets/migrate.png

Run python manage.py createsuperuser: /assets/wagtail-heroku-deployment.assets/superuser.png