This post is the first post of a series on how to deploy a Django project on Heroku.
You will see that the main idea behind these posts is not to build a functional Django app. Instead, what I want to do is to give you a bunch of good practices on how to build a Django app with different environments for testing, developing and production, useful packages installed, Internationalization and Localization properly configured, PosgreSQL installed, and much more.
PART I
This post explains how to create a Django project on Heroku. For this first part, I followed the tutorial Django on Heroku, and some ideas from the deploydjango website.
The topics covered here are:
- set up Heroku
- set up PostgreSQL
- start a Django app in a Virtualenv
- set the Procfile
- specify the dependencies
- separate your applications and your libraries
- set the settings.py file
- push your app in Heroku
- change the name of your app
Set up Heroku
First of all, you need to set up a Heroku user account. It is free and instant.
Second, you need to have installed Python, Pip and Virtualenv on your computer. See this post to find more information on how to install them on Mac OS X.
You need to install the Heroku Toolbelt on your local computer (your development environment). It gives you access to the Heroku command-line client (to create and manage Heroku apps), The Foreman (an easy option for running your apps locally), and Git (a revision control system).
Once installed, log in to Heroku from your command shell:
$ heroku login
If it is the first time you use Heroku, it will ask if you want to create a public key. Enter yes to generate one, you will need it to push code later on.
Set up PostgreSQL
In my case I have Mac OS X, Mountain Lion, and I used the Graphical Installer, recommended on the download page of PostgreSQL. It includes PostgreSQL, pgAdmin and the StackBuilder utility, for installation of additional packages.
During the installation process, you will need to set a password for the database superuser account (on Postgres).
Start a Django project in a Virtualenv
First, we need to create a directory for your project.
$ mkdir myfolderproject
$ cd myfolderproject
This directory will contain both the virtual environment and the Django application. We create the virtual environment with the flag –no-site-packages, which indicates that only the packages installed in the virtual environment will be used. If your version of Virtualenv is 1.7 or higher you can skip this flag, as it is the default behaviour.
$ virtualenv myenv –no-site-packages
$ source myenv/bin/activate
where the second line activates the virtual environment. Anytime, you can exit the virtual environment typing deactivate.
In order to install Django, we will use the django-toolbelt, which includes the following packages:
– django
– psycopg2
– gunicorn (WSGI server)
– dj-database-url (a Django configuration helper)
– dj-static (a Django static file server)
With your virtual environment active:
$ pip install django-toolbelt
With Mac OS X, the package psycopg2 might give you an installation error. If you type
$ pg_config
hopefully it will give you a not found error (which means I can help you with this error…). You need to find the path of this command with
$ sudo find / -name pg_config
which should be something like /Library/PostgreSQL/9.3/bin. You need to add it to the $PATH variable, so open the .bash_profile file and add the line:
export PATH=/Library/PostgreSQL/9.3/bin:$PATH
Finally, restart your terminal and try again the installation. Hopefully it will work 😉
If you want to see which version of Django has been installed:
$ python
>>> import django
>>> print django.VERSION
which for me was Django 1.6.1.
Finally, let’s create the Django project:
$ django-admin.py startproject myproject .
The dot at the end indicates that the app will be installed without creating an additional folder.
Procfile
A Procfile is a text file that declares the commands that will be run by your application dynos on the Heroku platform.
Create the file Procfile (you should not change this name) in the root directory of your app (at the same level where manage.py lives), and write:
web: gunicorn myapp.wsgi
You should be able to start your django app locally using the Procfile and Foreman, by typing:
$ foreman start
You will se something like
Listening at: http://0.0.0.0:5000 (1489)
Go to http://0.0.0.0:5000 with your web browser and check that you see the Django “It worked!” message. Type ctrl+c to exit.
Dependencies
Heroku recognizes Python applications by detecting a requirements.txt file in the root of a repository. This file, should contain the packages installed inside your virtual environment. You can create this file automatically using pip (you must be in your root directory, at the same level as your manage.py file):
$ pip freeze > requirements.txt
Having a top-level requirements.txt file is mandatory for Heroku. However, a best practice is to use separate .txt files to specify the dependencies needed for development and/or production.
At the same level of the requirements.txt we create a requirements folder that contains the packages used in any of these cases: development, production and testing (do not remove the requirements.txt file).
$ mkdir requirements
$ touch requirements/{common.txt,dev.txt,prod.txt,test.txt}
The file common.txt holds the dependencies that are shared between environments, like Django. The other .txt files should include the line
-r common.txt
followed by the packages needed for that environment. This line tells pip to include the dependencies in that file. Here, there are some examples of packages and the environment in which they usually belong:
Common: django, django-pagination, django-tastypie, South
Dev: django-debug-toolbar
Prod: gunicorn, psycopg2
Test: coverage, nose
The idea is to have different environments depending on if you want to run your code for development, production or testing. For example, the following line allows you to install all the development requirements:
$ pip install -r requirements/dev.txt
Finally, the requirements.txt file should contain:
-r requirements/prod.txt
If you want you can create two different environments, one for developing and one for testing, with the dependencies listed on dev.txt and test.txt. Remember to include them in your .gitignore file (see below).
Separating applications and libraries
Another good practice is to create two separate folders: apps and libs inside your myproject folder. The first one, apps, will contain all your applications that have models, views, etc. In the other one, we will include the applications that contain helper functionalities, that don’t belong to any of the other applications.
In order for these folders to be considered as packages by django, you must include an empty file on each of them called __init__.py
$ cd myproject
$ mkdir apps libs
$ touch apps/__init__.py libs/__init__.py
In order to create an app in each of these folders, first you must go inside it. For example:
$ cd myapp/apps
$ django-admin.py startapp myapp
However, we have to write the correct path when importing the apps of this folder. For example, inside the file myapp/views.py, we should import the model MyModel in the file myapp/models.py as:
from myproject.apps.myapp.models import MyModel
And also, you need to update your settings.py file to include the path of your new application:
Django settings
The next step is to configure the application for the Heroku environment. If you want a more advanced configuration of your settings.py file, taking into account the different environments (development, production, etc), go to the next section.
Open the settings.py, located in myprojectfolder/myproject. There are a few things you should do:
1. Change the following variables to:
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ALLOWED_HOSTS = [‘yourappname.herokuapp.com’]
where yourappname.herokuapp.com is the URL of your project live on Heroku.
2. Write the following after the DATABASES declaration:
import dj_database_url
DATABASES[‘default’] = dj_database_url.config()
3. Add the following declaration at the end of the file:
SECURE_PROXY_SSL_HEADER = (‘HTTP_X_FORWARDED_PROTO’, ‘https’)
4. Add/modify the following to configure your static files:
Finally, you have to change the file wsgi.py (which is loacated at the same folder than the settings.py file) to serve static files in production. Select the line:
application = get_wsgi_application()
and replace it with
from dj_static import Cling
application = Cling(get_wsgi_application())
Check out that your app is running with foreman start.
Git and Heroku
Once we have tested the application, we need to store the project in a Git repository. However, the myprojectfolder folder contains some extra files that we don’t want in our repository. Go inside the myprojectfolder, at the same level of the Procfile file and create the file .gitignore.
$ touch .gitignore
Open it and write:
myenv
*.pyc
myproject/ignore_directory
This indicates Git to ignore your virtual environment folder, all the compiled files created by python and an example of a directory to ignore, named ignore_directory. Feel free to change this file with the files or folders you want to ignore.
Then, we initialize a new Git repository and save our changes:
$ git init
$ git add .
$ git commit -m “First commit of my django app”
Next, we need to create a place to push to from Heroku:
$ heroku create appnameonheroku
and then push our application repository:
$ git push heroku master
If you get an error like Permission denied (publickey), is because you have to upload your public key to Heroku, see this post. Try
$ heroku keys:add ~/.ssh/id_rsa.pub
if you have a key, or just
$ heroku keys:add
if you want to create one.
Once you successfully push your repository on Heroku, you can visit your app with
$ heroku open
Also, ensure you have one dyno
$ heroku ps:scale web=1
Change the name of you app.
If you didn’t specify the name of your app, here appnameonheroku, it might have some name like simple-spring-9999 or murmuring-dawn-3477. If you go to the Heroku homepage, you can select your app and change its name. However, you have to update the git remote for the app, see this post:
$ git remote rm heroku
$ git remote add heroku git@heroku.com:yourappname.git
Note: if you have changed the name of your app, don’t forget to update the setting
ALLOWED_HOSTS.
More changes
Every time your make a change and want to upload it to Heroku, remember that you must type:
$ git add .
In case you want to delete the last command, type:
$ git reset
otherwise:
$ git commit -m “Describe your changes”
$ git push heroku master
Remember to be logged in to Heroku anytime you run these commands.
That’s all for today!
Hope it worked for you too 🙂
Do you want to go to the second part of this post?
How to set a Django app on Heroku. Part II.
Please, click on the g+1 if this post was useful 🙂
Marina Mele has experience in artificial intelligence implementation and has led tech teams for over a decade. On her personal blog (marinamele.com), she writes about personal growth, family values, AI, and other topics she’s passionate about. Marina also publishes a weekly AI newsletter featuring the latest advancements and innovations in the field (marinamele.substack.com)