DEV Community

Cover image for How to deploy a Django App on Heroku in less than 5 minutes
Jonatan
Jonatan

Posted on

How to deploy a Django App on Heroku in less than 5 minutes

In this short tutorial, I will demonstrate how to deploy a Django project on Heroku while serving static files from your own domain.

Prerequisites:

You do not need to use virtualenv, but it is highly recommended to use an isolated environment for different projects. Another option to virtualenv, for deploying to Heroku, is pipenv.

Installing Django, virtualenv, pip and the heroku-cli on Ubuntu

sudo apt install python3
sudo apt install python3-django
sudo apt install python3-virtualenv
sudo apt install python3-pip
sudo snap install --classic heroku
Enter fullscreen mode Exit fullscreen mode

Creating a Django project

We can now create our Django project named myproject

django-admin startproject myproject
Enter fullscreen mode Exit fullscreen mode

Setting up your virtual environment

You now want to go to the root of your project and set up your virtual environment.

Navigate to your project

cd myproject
Enter fullscreen mode Exit fullscreen mode

Make a virtual environment

virtualenv venv
Enter fullscreen mode Exit fullscreen mode

Activate your virtual environment

source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Install Django in your virtual environment

pip install django
Enter fullscreen mode Exit fullscreen mode

Creating a new Heroku project

We now want to create a new Heroku project.

heroku create
Enter fullscreen mode Exit fullscreen mode

This will create a domain at https://example.herokuapp.com so select the project name to be the domain you want your project to be hosted at. (You can later add a custom domain).

Changing the secret key

First, we want to change the SECRET_KEY to an environment variable, because we want to have a unique SECRET_KEY in production that we don't push to version control.

SECRET_KEY = os.getenv('SECRET_KEY', 'change-in-production')
Enter fullscreen mode Exit fullscreen mode

Now we can set our production environment variable with

heroku config:set SECRET_KEY=very-long-secret-key
Enter fullscreen mode Exit fullscreen mode

We now need to set up static files and turn off DEBUG mode in production.

Setting up static files

We are going to use whitenoise to serve static files. First, we need to install it

pip install whitenoise
Enter fullscreen mode Exit fullscreen mode

Next, we add the whitenoise middleware to the top of the middleware section

MIDDLEWARE = [
    'whitenoise.middleware.WhiteNoiseMiddleware', # First in list
    ...
]
Enter fullscreen mode Exit fullscreen mode

Next, we set up the path of our static files

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
Enter fullscreen mode Exit fullscreen mode

We then install django_heroku to configure default values.

pip install django_heroku
Enter fullscreen mode Exit fullscreen mode

We enable the django_heroku settings, but set staticfiles and allowed_hosts to False, because we want to specify our own static file options and change allowed_hosts from the django_heroku default value ['*'] to prevent Host Header attacks.

django_heroku.settings(locals(), staticfiles=False, allowed_hosts=False)
Enter fullscreen mode Exit fullscreen mode

At the bottom of the settings.py file, we will now add settings specific to Heroku.

if "DYNO" in os.environ:
    STATIC_ROOT = 'static'
Enter fullscreen mode Exit fullscreen mode

Initializing git

We will now add git to our project.

git init
Enter fullscreen mode Exit fullscreen mode

Adding Heroku to your git remotes

heroku git:remote -a example
Enter fullscreen mode Exit fullscreen mode

Disabling DEBUG and settings allowed hosts

We now want to disable DEBUG in production and add our domain to our allowed hosts. We add these options in the if "DYNO" in os.environ block because we only want these settings to be in effect in production.

if "DYNO" in os.environ:
    STATIC_ROOT = 'static'
    ALLOWED_HOSTS = ['example.herokuapp.com']
    DEBUG = False
Enter fullscreen mode Exit fullscreen mode

Adding the Procfile

First, we will add the Procfile. To do this just add a file called Procfile (without any extension) to the root of your project. On ubuntu and mac simply write

touch Procfile
Enter fullscreen mode Exit fullscreen mode

We then install gunicorn which is the HTTP server we use in production on Heroku.

pip install gunicorn
Enter fullscreen mode Exit fullscreen mode

while in the terminal while in the root directory. Next, add the following to the file

web: gunicorn myproject.wsgi --log-file -
Enter fullscreen mode Exit fullscreen mode

Adding the requirements.txt file

Our last step is to create the requirements.txt file, which will specify all the packages that we have used. Since we used a virtual environment, this step is very easy. All we have to do is type

pip freeze > requirements.txt
Enter fullscreen mode Exit fullscreen mode

in the terminal while being in our projects root directory. This will add all our packages installed through pip to the requirements.txt file automatically.

If you weren't using a virtual environment, you can also manually create a requirements.txt file in the root directory and manually add all the requirements. If you did everything correctly your requirements.txt file should look like

asgiref==3.4.1
dj-database-url==0.5.0
Django==3.2.7
django-heroku==0.3.1
gunicorn==20.1.0
psycopg2==2.9.1
pytz==2021.1
sqlparse==0.4.2
whitenoise==5.3.0
Enter fullscreen mode Exit fullscreen mode

Deploying to Heroku

We are now ready to deploy our project.

git add .
git commit -m "My first project is ready to be deplayed"
git push heroku main
Enter fullscreen mode Exit fullscreen mode

And we are done! Your project is now deployed to Heroku.

Optional settings for production

If you want to make sure your project only works over https you want to add the following options to your production settings.

if "DYNO" in os.environ:
    STATIC_ROOT = 'static'
    ALLOWED_HOSTS = ['example.herokuapp.com']
    DEBUG = False
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    SECURE_SSL_REDIRECT = True
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
Enter fullscreen mode Exit fullscreen mode
  • CSRF_COOKIE_SECURE  -  Ensures your CSRF cookies will be served over https.
  • SESSION_COOKIE_SECURE  -  Ensures your session cookies will be served over https.
  • SECURE_PROXY_SSL_HEADER & SECURE_SSL_REDIRECT  -  Will redirect all HTTP traffic to https

Additional reading

Discussion (4)

Collapse
jungle_jim profile image
jungle_jim

This article is impossible to follow - Firstly there is no continuity and secondly the examples don't work

Collapse
jonatanvm profile image
Jonatan Author

Hi, thanks for the feedback which examples did not work for you and which sections did you find hard to follow? :)

Collapse
wavesailor profile image
wavesailor

Nice article but I lost you when you got to the section "Changing the secret key". Your tutorial was step by step and then I did not know where to changes these keys.

Collapse
jonatanvm profile image
Jonatan Author

So by default your settings file will have a line that looks like this:

SECRET_KEY = "some long random key"
Enter fullscreen mode Exit fullscreen mode

You need to change this key in production (for security), which is why you should change it to an environmental variable.

SECRET_KEY = os.getenv('SECRET_KEY', 'change-in-production')
Enter fullscreen mode Exit fullscreen mode

You can leave the default key to "change-in-production" as it will only be used in development.

After you have set your app to take it's SECRET_KEY from an environmental variable you need to set that environmental variable for your app on heroku. For this you need to download the Heroku CLI. After which you can set your apps environmental variables with the command:

 heroku config:set SECRET_KEY=very-long-secret-key
Enter fullscreen mode Exit fullscreen mode

You should replace "very-long-secret-key" with a very long password.