Configuring Django Apps for Heroku
Last updated 15 November 2017
Heroku supports all types of Python applications, including Django applications. However, Django’s complex configuration patterns can make life a little difficult for cutting-edge developers.
This best-practice guide outlines all Django-specific requirements for deploying Python applications on Heroku.
Creating a new Django project
When starting a brand new Django project, you can use the official Heroku Django Starter Template to get started immediately. This template includes all best-practices and recommendations outlined in this article, and is strongly recommended for getting started with Django on Heroku.
Assuming you already have Django installed, you can create a new pre-configured Django project with the following command:
$ django-admin startproject --template=https://github.com/heroku/heroku-django-template/archive/master.zip --name=Procfile myproject
That’s it! This will give you a brand new, fresh Django application that will “just work” on Heroku.
Migrating an existing Django project
You may want to migrate an existing Django project. Let’s go through all of the components included in the starter template mentioned above.
First, and most importantly, Heroku web applications require a Procfile.
This file (named
Procfile) is used to explicitly declare your application’s process types and entry points. It is located in the root of your repository.
web: gunicorn myproject.wsgi --log-file -
This Procfile requires Gunicorn, the production web server that we recommend for Django applications. For more information, see Deploying Python Applications with Gunicorn.
$ pip install gunicorn ... $ pip freeze > requirements.txt
On Heroku, sensitive credentials are stored in the environment as config vars. This includes database connection information (named
DATABASE_URL), which is traditionally hardcoded in Django applications.
The dj-database-url package parses the
DATABASE_URL environment variable and converts it to Django’s desired configuration format, automatically.
$ pip install dj-database-url ... $ pip freeze > requirements.txt
# Update database configuration with $DATABASE_URL. import dj_database_url db_from_env = dj_database_url.config() DATABASES['default'].update(db_from_env)
Database connection persistence
By default, Django will only create a new persistent database connection for every request cycle of your application. This is a very expensive operation, and can slow down your Django application.
Luckily, Django provides persistent connections, which are a great way to improve the performance of your Django application.
# Update database configuration with $DATABASE_URL. import dj_database_url db_from_env = dj_database_url.config(conn_max_age=500) DATABASES['default'].update(db_from_env)
For more information, see Concurrency and Database Connections in Django.
Static assets and file serving
Django settings for static assets can be a bit difficult to configure and debug. However, if you just add the following settings to your
settings.py, everything should work exactly as expected:
Older versions of Django won’t automatically create the target directory (
collectstatic uses, if it isn’t available. You may need to create this directory in your codebase, so it will be available when
collectstatic is run. Git does not support empty file directories, so you will have to create a file inside that directory as well.
For more information, see Django and Static Assets.
By default, Django does not support serving static files in production. We recommend using the WhiteNoise project for best-practice serving of static assets in production.
$ pip install whitenoise ... $ pip freeze > requirements.txt
# Simplified static file serving. # https://warehouse.python.org/project/whitenoise/ STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
from django.core.wsgi import get_wsgi_application from whitenoise.django import DjangoWhiteNoise application = get_wsgi_application() application = DjangoWhiteNoise(application)
That’s it! See the WhiteNoise documentation for more details.