Skip to content

Instantly share code, notes, and snippets.

@asnr
Created July 5, 2015 08:00
Show Gist options
  • Save asnr/0b0a46d3dddeb2aae14a to your computer and use it in GitHub Desktop.
Save asnr/0b0a46d3dddeb2aae14a to your computer and use it in GitHub Desktop.
How to get django running with a Postgres backend on Heroku

Django, Postgres then Heroku

Django is running using sqlite local backend, let's upgrade to Postgres.

Install & configure postgres

Install Postgres. On mac, homebrew works or you can use Postgres.app, which comes with extra goodies. If you install the app, make sure to add the application directory (probably /Applications/Postgres.app/Contents/Versions/9.3/bin/) to $PATH so that psql, the helper executables and pg_config can be found.

Create user and db

Login. Check dbs with \list, check users with \du. It's pretty stark. Create a user from the command line:

createuser res_dir_owner -S -D -R

(remember those tools?). The options are, in order, not superuser, not db creator and not role creator.

Create a db:

createdb -U $CREATORUSER --locale=en_US.utf-8 -E utf-8 -O $OWNERUSER $DBNAME -T template0

The options should be obvious apart from -T. Postgres databases are actually copies of other databases, and the template0 db is by convention a virgin. template1 is used for local-preference filled starter.

You can change db owner in psql:

alter database $DBNAME owner to $NEWOWNER;

And a user's password:

alter user $USER with password '$NEWPSSWD';

Connect to Django

In settings.py:

DATABASES = {
    'default': {
		'ENGINE': 'django.db.backends.postgresql_psycopg2',
		'NAME': '$DBNAME',
		'USER': '$USER',
		'PASSWORD': '$PASSWORD',
		'HOST': 'localhost',
		'PORT': '5432',
	 }
}

Then ./manage.py syncdb away.

Connecting to Postgres using Heroku tools

First we will use the Heroku Python tool dj_database_url to configure our database. What we had previously is equivalent to

DATABASES = {
	'default': dj_database_url.config(
		default='postgres://USER:PASSWORD@HOST:PORT/DBNAME')
}

To remove the configuration information from our source code and begin using foreman at the same time, move the database URL to the .env (which should be in the same directory as Procfile):

USER="$APPNAME"
DATABASE_URL="postgres://$USER:$PASSWORD@$HOST:$PORT/$DBNAME"

(note that we don't really need to define $USER just yet, but it doesn't hurt). Now to run our app using foreman we will also need to create Procfile:

web: gunicorn PROJECTNAME.wsgi:application --log-file -

Here PROJECTNAME should be the name you used as the argument to django-admin.py startproject. In addition, create the requirements.txt file in the same directory, after installing all the dependencies:

pip freeze > requirements.txt

Now you can run the app by calling foreman start on the command line. Doing so will reveal one deficiency, however: the static files are not being served!

Serving static files with foreman and Gunicorn

Add the following line to settings.py:

STATIC_ROOT = 'staticfiles'

This variable holds the name of the directory from which static files will be served in production. Note that this is not where the source files should live. We might as well add

# 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 = ['*']

and we didn't add, but might need to add

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

Make sure we already had

STATIC_URL = '/static/'

We will also need to change wsgi.py. The last two lines of the default file are:

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

We will keep the former, but change the latter, so that we end up with

from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())

You should now be able to serve static files using foreman start.

To production!

  • if app is already created, just need to add the remote repo with

      git remote add heroku git@heroku.com:$APPNAME.git
    
  • push to heroku repo

  • create database:

      heroku run python manage.py syncdb
    
  • Enjoy!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment