Configuring Django Apps for Heroku
Last updated 11 December 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.
Be aware that this documentation serves as an instruction manual on how to perform all the best practices manually. To do them automatically, check out the django-heroku Python module, which will automatically configure your Django application for deployment on Heroku.
Please note, the web server and
Procfile steps are still necessary when using django-heroku.
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.
Django does not support serving static files in production. However, the fantastic WhiteNoise project can integrate into your Django application, and was designed with exactly this purpose in mind.
See the WhiteNoise documentation for more details.
First, install WhiteNoise with
$ pipenv install whitenoise Adding whitenoise to Pipfile's [packages]...
Next, install WhiteNoise into your Django application. This is done in
settings.py’s middleware section (at the top):
MIDDLEWARE_CLASSES = ( # Simplified static file serving. # https://warehouse.python.org/project/whitenoise/ 'whitenoise.middleware.WhiteNoiseMiddleware', ...
Finally, if you’d like gzip functionality enabled, also add the following setting to
# Simplified static file serving. # https://warehouse.python.org/project/whitenoise/ STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
Your application will now serve static assets directly from Gunicorn in production. This will be perfectly adequate for most applications, but top-tier applications may want to explore using a CDN with Django-Storages.
To learn more, see Django and Static Assets on Heroku Dev Center.