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.
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:
python3 -m venv mysite\envmysite\env\Scripts\activate.bat
On unix or mac:
python3 -m venv mysite/envsource mysite/env/bin/activate
Install wagtail
pip install wagtail
Generate starter site
cd mysitewagtail start mysite mysite
First
mysite
is the project name and secondmysite
is the root directory for the project. If you already insidemysite
folder, just typewagtail start mysite .
instead.
Django uses
django-admin startproject
instead ofwagtail 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
git initgit add README.mdgit commit -m "Init commit"git branch -M mastergit remote add origin https://github.com/<username>/<repo-name>.gitgit push -u origin master
Or push existing repository from the commmand line
git remote add origin https://github.com/<username>/<repo-name>.gitgit branch -M mastergit 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 asFalse
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 needwhitenoise
to serve static files.
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:
pip install psycopg2pip install django-toolbeltpip install whitenoise
Then update DATABASES
in base.py
settings:
# 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:
pip freeze > requirements.txt
Update production.py
Add following to production.py
(production settings module):
from __future__ import absolute_import, unicode_literalsimport osimport dj_database_urlDATABASES['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 headersALLOWED_HOSTS = ['*']env = os.environ.copy()SECRET_KEY = env['SECRET_KEY']
from __future__ import absolute_import, unicode_literals
line should be at the top ofproduction.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:
web: gunicorn locallibrary.wsgi --log-file -
Create runtime.txt
file and copy the following text into it:
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:
*.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:
git commit -m "First version of application"
After that, push all previous changes to the github remote repository:
git push origin master
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:

Add github connection
Then go to Deploy
tab of newly created app, add github connection to it:

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
:

Add DJANGO_SETTINGS_MODULE
and SECRET_KEY
:

Deploy
Now go to Deploy
tab and scroll all the way down, click Deploy Branch
button for deployment.

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.

Run python manage.py migrate
:

Run python manage.py createsuperuser
:
