2

I have a basic django app (Newsdiffs)that runs just fine at localhost:8000 with python website/manage.py runserver but I'd like to migrate it to Heroku and I can't figure out what my next step is.

I thought getting it running locally would translate to running it on Heroku, but I'm realizing that python website/manage.py runserver is launching the dev settings and I'm not sure how to tell it to use the main settings.

All that is in my Procfile is this:

web: python website/manage.py runserver

Locally, that works fine, though it launches it at http://127.0.0.1:8000/ which is probably not what I want on Heroku. So how do I figure out where to set the hostname and port? I don't see either in the app anyplace.

Pynchia
  • 10,996
  • 5
  • 34
  • 43
Amanda
  • 12,099
  • 17
  • 63
  • 91
  • 1
    Check in settings.py . Debug = flase .. some settings might be their.. – coder3521 Sep 16 '15 at 05:23
  • Why do you think to need to set the hostname and port? You don't. But you do need to actually read the very comprehensive documentation on Heroku's site about running Django. – Daniel Roseman Sep 16 '15 at 07:23
  • For example, I can't imagine what gave you the idea of putting runserver in your Procfile. You need to use gunicorn there. – Daniel Roseman Sep 16 '15 at 07:26
  • @DanielRoseman Thanks. I did actually read the extensive Heroku documentation and launch a django app successfully. But this django app isn't in wsgi, so I can't use gunicorn unless I rewrite/rewrap it. – Amanda Sep 16 '15 at 15:54
  • 2
    What? All Django apps are "in wsgi". That's how Django works. – Daniel Roseman Sep 16 '15 at 16:04
  • @DanielRoseman not, I'm discovering, if they just use Django's built in dev server. – Amanda Sep 27 '15 at 19:23
  • Not true. The dev server is a WSGI server, just not a particularly powerful or well-featured one. But you still haven't said what the difference is between your app and one that's "in wsgi". – Daniel Roseman Sep 27 '15 at 19:26
  • @DanielRoseman it isn't exactly "my app" -- I didn't write Newsdiffs, I'm just trying to get my own instance of it running. But ... they didn't list gunicorn as a requirement and there aren't any references to gunicorn in the code base, so that's one thing that I've found puzzling as I try to apply Heroku's Django documentation to this app. – Amanda Sep 27 '15 at 19:42
  • I really don't understand your issue. gunicorn is a requirement for running on Heroku, not in dev. So you need to install it, along with the other dependencies for running on Heroku, as described in the [Heroku docs on Django](https://devcenter.heroku.com/articles/getting-started-with-django). – Daniel Roseman Sep 27 '15 at 19:49
  • Backtracking a little bit, so I can get this sorted out piece by piece: http://stackoverflow.com/questions/32814227/where-is-hellodjango-wsgi – Amanda Sep 28 '15 at 01:10

2 Answers2

2

I have just drawn this list for myself two days ago. It was put together after having followed the steps described in Heroku's help pages for python.

It's by no means definitive nor perfect, and it will change, but it's a valid trace, since I was able to put the site online.

Some issues remain, to be checked thoroughly, e.g. the location of the media/ directory where files are uploaded should/could live outside your project for security reasons (now it works, but I have noticed if the dyno sleeps then the files are not reached/displayed by the template later). The same goes for the staticfiles/ directory (although this one seems to work fine).

Also, you might want to set django's debug mode to false.

So here it is:

My first steps to deploy an EXISTING django application to Heroku

ASSUMPTIONS:

a) your django project is in a virtual environment already

b) you have already collected all your project's required packages with

pip freeze > requirements.txt

and committed it to git

git add requirements.txt
git commit -m 'my prj requirements'

0) Activate your project's virtual environment

workon xyz  #using virtualenvwrapper

then go to your django project's directory (DPD for short) if not already taken there

cd ~/prj/xyz  (or cdproject with virtualenvwrapper if setup properly)

and create a new git branch for heroku twiddling to prevent messing things up

git checkout -b he

1) Create the app on heroku

heroku create xyz

that also adds heroku as a remote of your repo

2) Add the needed packages to requirements.txt

vi requirements.txt

add

dj-database-url==0.3.0
django-postgrespool==0.3.0
gunicorn==19.3.0
psycopg2==2.6
django-toolbelt==0.0.1
static3==0.5.1
whitenoise==2.0.3

3) Install all dependencies in the local venv

pip install -r requirements.txt --allow-all-external

4) Setup the heroku django settings

cd xyz

create a copy

cp setting.py settings_heroku.py

and edit it

vi settings_heroku.py

import os
import dj_database_url

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'), )
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

replace django's std db cfg with

DATABASES['default'] =  dj_database_url.config()
DATABASES['default']['ENGINE'] = 'django_postgrespool'

and

WSGI_APPLICATION = 'xyz.wsgi_heroku.application'

5) Configure the necessary environment variables (heroku configs)

edit the .env file

vi .env

e.g.

DJANGO_SECRET_KEY=whatever
EMAIL_HOST_USER=youruser@gmail.com
EMAIL_HOST_PASSWORD=whateveritis

and/or set them manually if needed (in my case .env had no effect, wasn't loaded apparently, and had to set the vars manually for now)

heroku config:set DJANGO_SECRET_KEY=whatever
heroku config:set EMAIL_HOST_USER=youruser@gmail.com
heroku config:set EMAIL_HOST_PASSWORD=whateveritis

6) Create a separate wsgi file for heroku

cd xyx
cp wsgi.py wsgi_heroku.py

and edit it to make it point to the right settings

vi wsgi_heroku.py
from whitenoise.django import DjangoWhiteNoise
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xyz.settings_heroku")
application = get_wsgi_application()
application = DjangoWhiteNoise(application) 

7) Make sure all the templates use

{% load staticfiles %}

8) Define the Procfile file so that it points to the right wsgi

e.g.

cd ~/prj/xyz (DPD)
vi Procfile

add

web: gunicorn xyz.wsgi_heroku --log-file -

9) Collect all static content into DPD/staticfiles/

locally, make sure django points to the right wsgi settings

export WSGI_APPLICATION=blogger.wsgi_heroku.application
python manage.py collectstatic

10) add the changes to the local git repo (he branch)

git add --all .
git commit -m 'first 4 heroku'

11) check the whole thing works locally

heroku local # in heroku's help they also add `web`, not needed?!

12) push your code to heroku

git push heroku he:master

13) make sure a instance of the app is running

heroku ps:scale web=1

14) create the tables on the heroku DB

heroku run python manage.py migrate

Note: if you see a message that says, “You just installed Django’s auth system, which means you don’t have any superusers defined. Would you like to create one now?”, type no.

15) add the superuser to the heroku DB

heroku run bash
python manage.py createsuperuser

and fill in the details, as usual

16) Populate the DB with the necessary fixtures

heroku run python manage.py loaddata yourfile.json

17) Visit the website page on heroku's webserver

heroku open

or go to

https://xyz.herokuapp.com/

and the admin

https://xyz.herokuapp.com/admin/

and the DB

https://xyz.herokuapp.com/db

Useful commands:

  • View the app's logs

    heroku logs [--tail]

  • List add-ons deployed

    heroku addons

    and use one:

    heroku addons:open <add-on-name>

  • Run a command on heroku (the remote env, where you are deploying)

    heroku run python manage.py shell heroku run bash

  • Set a config var on Heroku

    heroku config:set VARNAME=whatever

  • View the config vars that are set (including the DB's)

    heroku config

  • View postgres DB details

    heroku pg

Pynchia
  • 10,996
  • 5
  • 34
  • 43
2

If you know some python and have a lot of experience building web apps in other languages but don't totally understand where Heroku fits, I highly recommend Discover Flask, which patched a lot of the holes in my understanding of how these pieces all fit together.

Some of the things that I worked out:

  • you really do need an isolated virtual environment if you're going to deploy to Heroku, because Heroku installs Python modules from the requirements.txt file.

  • Gunicorn is a web server, and you definitely need to run your app under Gunicorn or it won't run on Heroku.

  • The "Procfile" doesn't just give the command you use to run the app locally. And Heroku requires it. So if you've got an app that was built to run on Heroku and it doesn't include a Procfile, they left something out.

  • You don't tell Heroku what your hostname is. When you run heroku create it should tell you what your domain name is going to be. And every time you run git push heroku master (or whatever branch you're pushing, maybe it isn't master), Heroku will (try to) restart your app.

  • Heroku doesn't support sqlite. You have to run your Production DB in Postgres.

This doesn't directly answer my question, but it does fill in some of the missing pieces that were making it hard for me to even ask the right question. RTFM notwithstanding. :)

Amanda
  • 12,099
  • 17
  • 63
  • 91