How to migrate your existing Django project to Heroku

Recently I had some fun with Heroku, the well known PaaS provider. I had a small personal Django project I use for invoicing that I ran locally with ./manage.py runserver when needed. That was a perfect candidate for the Heroku free plan because I need to access the app only occasionally.

In this tutorial I assume you have a basic knowledge of what Heroku is, and that you already know how to create and deploy a Python project on Heroku. In case you miss some basic information you can refer to the good Getting started tutorial on Heroku with Python.

Here I focus on my use case, which was to migrate an existing Django project on Heroku platform. My existing Django project was structured in accordance to the best practices I read in the wonderful Two Scoops of Django book, so my project structure was similar to this:

django/
├── project
│   ├── __init__.py
│   ├── settings
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── local.py
│   │   └── production.py
│   ├── urls.py
│   ├── wsgi.py
├── app
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   ├── views.py
└── manage.py
requirements
├── base.txt
├── local.txt
└── production.txt

See how I have different settings for each deploy environment: one for local development, one for production. All common settings go in base.py.

See also how I have a different requirements file for each environment, for example I have django-debug-toolbar in local.txt, while I have psycopg2 in production.txt. All common requirements are in base.txt.

For Heroku I created a file heroku.txt under requirements/ directory with the following content:

-r base.txt

dj-database-url==0.3.0
psycopg2==2.6.1
whitenoise==2.0.2
django-storages==1.4.1
boto==2.38.0

On Heroku I will use Postgres as database backend (which is free , and dj-database-url to configure the database parameters using an environment variable, which is already set by Heroku.

I’ll also use whitenoise to handle static files directly from django and django-storages to handle media files on Amazon S3.

The first thing you have to do to tell Heroku you are deploying a python project is to put a

requirements.txt

file in the root of your git project. You can create a file with this content to include the requirements specific to Heroku:

-r requirements/heroku.txt

Then you have to do some modification to your settings, for deploy on Heroku platform:

# Parse database configuration from $DATABASE_URL
import dj_database_url
from os import environ

from .base import *

ALLOWED_HOSTS = ['yourappname.herokuapp.com']

DATABASES = {
 'default': dj_database_url.config()
}

WSGI_APPLICATION = 'yourproject.wsgi_heroku.application'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
STATIC_ROOT = root('static_root')

INSTALLED_APPS += ('storages',)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = environ['AWS_SECRET_ACCESS_KEY']
AWS_STORAGE_BUCKET_NAME = 'yourbucketname'

Then you have to edit your wsgi.py file to make use of whitenoise for static files, the file whould look something like this. Save it in a different wsgi_heroku.py file:

import os
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "yourproject.settings.heroku")

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

Now you can create you Heroku application:

heroku create --region eu yourappname

In the root directory of your project you should have a Procfile, used by Heroku to know how to launch the web worker, in our case the Procfile should contain just one line like the following:

web: gunicorn --pythonpath django yourproject.wsgi_heroku --log-file -

Now push the code on Heroku:

git push heroku master

Then you can create the database schema with the usual migrate command, run on the Heroku instance:

heroku run python django/manage.py migrate

Migrating data

If you have some data to migrate you can use a couple of command from core Django

./manage.py dumpdata yourapp > yourapp/fixtures/app_data.json

Then you can import the data on Heroku instance:

heroku run python django/manage.py loaddata app_data

Media files on AWS S3

If your application needs some user uploaded data, you can use Amazon S3 to store the files, by using django-storages app to configure the correct Storage for you media files.

The configuration of django-storages is out of scope for this tutorial, but you can find some good tutorials on the web.

Advertisements

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s