Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Django/Heroku Quickstart for Existing Applications

DZone's Guide to

Django/Heroku Quickstart for Existing Applications

· Web Dev Zone
Free Resource

Prove impact and reduce risk when rolling out new features. Optimizely Full Stack helps you experiment in any application.

Getting a brand new Django application running on Heroku is fairly simple. There is a great tutorial for it on devcenter.heroku.com. I would recommend going through that, and getting it working. Here is my short version of their getting started notes, without the virtualenv and Django command stuff you probably already know.

wget -qO- https://toolbelt.heroku.com/install.sh | sh
heroku login
heroku create --stack cedar
echo 'web: python manage.py runserver 0:$PORT' > Procfile
heroku addons:add shared-database 
git push heroku master  # if you're in a branch locally, you can git push -f heroku localbranch:refs/heads/master
heroku run python manage.py syncdb
heroku ps:scale web=1
heroku ps
heroku logs

 

That should be enough to get a brand new Django app running. If you have an existing Django application, however, their documentation doesn't provide much guidance on common pitfalls.

First of all, you may need a mechanism to over-ride settings.py on the production Heroku instance. First, you can add an environment variable:

heroku config:add ENVIRONMENT=production

With that variable, you can easily create an over-ride for settings.py called settings_production.py:

# at the END of settings.py:
import os
ENVIRONMENT = os.environ.get('ENVIRONMENT', 'dev')  # dev, production, qa, etc
exec('from settings_%s import *' % ENVIRONMENT)

Heroku gives you a shared database for free. You can see the connect string on it with the heroku config command:

...
DATABASE_URL => postgres://foobar:password@ec2-ip-address.amazonaws.com/instance
...

This would translate into the following in settings_production.py

DATABASES = {
    'default': {
        'ENGINE': 'postgresql_psycopg2',
        'NAME': 'instance',
        'USER': 'foobar',
        'PASSWORD': 'password',
        'HOST': 'ec2-ip-address.amazonaws.com',
        'PORT': '',  # leave blank
    }
}

The Heroku directions for switching from Django's development web server to gunicorn don't work for Django 1.3, where there is no WSGI file. After adding gunicorn to requirements.txt, and 'gunicorn' to INSTALLED_APPS, I changed Procfile to the following:

web: python manage.py run_gunicorn -b 0.0.0.0:$PORT

 

Getting Django's staticfiles feature working was a little trickier. Heroku gives you a "ephemeral" file system, meaning that any changes you write to disk will not survive the next deploy, and may not even survive between heroku command-line sessions. This means that collectstatic must be run as part of the deploy, which you can also do in Profile:

web: python manage.py collectstatic --noinput; python manage.py run_gunicorn -b 0.0.0.0:$PORT

Lastly, I wanted gunicorn to (at least temporarily) serve up the static resources itself. To do that, you will need to add the following to your urls.py:

urlpatterns += patterns('',
    (r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)

That was enough to get my small existing Django app running. I'm still trying to figure out how to migrate the old MySQL instance to the Heroku Postgres instance, and how to setup SSL. Stay tuned!

With SDKs for all major client and server side platforms, you can experiment on any platform with Optimizely Full Stack.

Topics:

Published at DZone with permission of Chase Seibert, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}