topshelf_deploy

Created: 2014-05-19 05:04
Updated: 2014-07-03 22:42

README.md

How to deploy an already existing Django app to Heroku

Visit the live page here on Heroku (NOTE: It's still in prototype mode)

Getting Started

These instructions assume that you are running Ubuntu/OS X.

Windows users will NOT be able to push to Heroku. You will need to setup a virtual machine that runs Linux, Ubuntu, or OS X. This was helpful with getting an Ubuntu virtual machine started.


Ok, time to go through Heroku's instructions, with my notes.


$ mkdir hellodjango && cd hellodjango

Make sure you’re using the latest virtualenv release. If you’re using a version that comes with Ubuntu, you may need to add the --no-site-packages flag.
If you already have a project or project/app created, you can skip this.


$ virtualenv venv

UBUNTU USERS, DO THIS INSTEAD: **$ virtualenv venv --no-site-packages**

Heroku didn't explain the reason for it. It's important! It stops your machine's applications from loading up in your virtualenv.

It will keep your requirements.txt file clean. Heroku will try to load everything that goes into requirements.txt and will throw errors because it's loading things that are only for your machine.


$ source venv/bin/activate

Run this every time you edit your project. **The virtualenv can be stored in your project's root.**


$ pip install django-toolbelt

This is fine. You may also need to install other packages into your virtualenv that your project uses (South, etc.).


$ django-admin.py startproject hellodjango .

Start your project if you're not deploying an existing project.


web: gunicorn hellodjango.wsgi

First, create a Procfile at your project root, where manage.py is. Do touch Procfile, then edit that file in a text editor. **DO NOT CREATE PROCFILE.txt.**

Heroku assumes that you know what a Procfile is. Heroku called it a text file, which is really confusing to first-time users. Procfile is a standalone file which you can edit in any text editor.

Heroku needs to run 0.0.0.0:8000 so try not to change the default-- you may end up just changing it back later.

Here's how to change the default, but it's best to avoid changing it.



What heroku totally forgot to address: your database. This was the biggest headache of all. If you're running Postgres, great. You'll have fewer problems. Make sure to sync and do schemamigrations. Skip the rest of this section.

If you're running another database, you'll need to convert it to Postgres. There are three options:

I chose #3. I had scraped a lot of data from external sources and just created another Postgres database, synched my models to it, imported the data with manage.py, and then did a schemamigration. It's not the best one to use if you have a lot of data in your existing database.

Converting the database was the most difficult part. Make sure to get this working before you move forward.


$ foreman start

Test out your app here. Should run ok if you've done the above steps properly.


$ pip freeze > requirements.txt

Requirements.txt should be at your project's root level, with manage.py and Procfile. Check the file to make sure the following are installed (versions will change):

  • Django==1.6
  • dj-database-url==0.2.2
  • dj-static==0.0.5
  • gunicorn==18.0
  • psycopg2==2.5.1
  • static==0.4
  • wsgiref==0.1.2

You may also need to add some other packages manually to avoid errors when pushing to heroku. I had to add a Requests package into the file, because my views.py used it.


Add to the bottom of settings.py:

# Parse database configuration from $DATABASE_URL
import dj_database_url
DATABASES['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 headers
ALLOWED_HOSTS = ['*']

# Static asset configuration
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'

STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), )

NOPE. This didn't work.

Replace their database setting with: DATABASES = {'default':dj_database_url.config(default='postgres://localhost')}

Here's why.

You need to do more to get this to work. You may already have some other settings. Get rid of any of the same settings taht Heroku wants to use (BASE_DIR, DATABASES, and ALLOWED HOSTS are loaded by default when you create a project). Get rid of your Postgres database settings completely!

Make sure to add Heroku's settings to the bottom of settings.py.


Wsgi.py:

from django.core.wsgi import get_wsgi_application
from dj_static import Cling

application = Cling(get_wsgi_application())

Replace your entire wsgi file with this. Don't just add it to the end of what you have already.


Create a .gitignore file and add:

venv *.pyc staticfiles

This should also be at your project's root, with manage.py, etc. Like Procfile, .gitignore is a standalone file.


Git and Heroku launch:

$ git init
$ git add .
$ git commit -m "my django app"
$ heroku create
$ git push heroku master

If you run into some problems here, just debug one by one. You may need to add a SSH key to Heroku before deploying.

Test out your app in Heroku. Heroku makes it seem like you're done here. You're not done!!! You still need to migrate over your database, if you have one. Instructions are buried after crap about dynos and logs.


To sync your database with Heroku:

$ heroku run python manage.py syncdb

You may also need to do heroku run python manage.py migrate {yourapp}

You can also run shell commands in Heroku with heroku run python manage.py shell, which may be helpful for synching and loading data.

Additional notes: I started using django-hstore to be able to store key-value pairs in the database. I had to make a few modifications to heroku:

heroku pg:psql Once in Heroku Postgres:
CREATE EXTENSION hstore; \q

After leaving heroku postgres:
heroku run python manage.py syncdb
heroku run python manage.py migrate {yourapp}
IF NEEDED: heroku run manage.py loaddata {data].json}
IF NEEDED: heroku run managep.y migrate tastypie (don't migrate this before loading your data. It'll generate errors)

Good luck!!

Cookies help us deliver our services. By using our services, you agree to our use of cookies Learn more