- Inside the project-directory add a
.env
,.gitignore
andProfile
file. Make sure they are in the project outer directory where themanage.py
file is found:
touch .env .gitignore Procfile
- From the Terminal, with a pipenv virtual environment running, after installing
django
andpsycopg2-binary
, add the other packages needed for deployment:
pipenv install whitenoise dj-database-url gunicorn django-cors-headers
-
If you haven't already initialized your project for git, run
git init
. -
Open the project in the editor with
code .
. Add this one line to yourProcfile
. Make sure to replace the example_django with the name of your project root.
# Replace example_django with your project root name:
web: gunicorn example_django.wsgi
- Add the following to your
.gitignore
file:
.env
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
db.sqlite3
db.sqlite3-journal
media
# General MacOS files to ignore
.DS_Store
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
- Update the
settings.py
file:
# At the top of the settings.py file add:
import os
import dj_database_url
You'll notice that the
settings.py
contains a warning not to leave your secret key in production so copy it into your.env
file and replace it with the following:
# SECURITY WARNING: keep the secret key used in production secret!
# Copy the entire SECRET_KEY line into your .env file and then change it to read:
SECRET_KEY = os.environ['SECRET_KEY']
Note the message to not run debug in production. Instead, we'll create an environment variable called MODE and set it to 'dev' in our .env file locally and 'production' in the Heroku configvars. We can use a ternary operator to set the DEBUG to True or False based on the environment variable.
# SECURITY WARNING: don't run with debug turned on in production!
# Replace the DEBUG = True with:
DEBUG = True if os.environ['MODE'] == 'dev' else False
The allowed hosts for your app depends on what front end apps you want to allow to connect to your back end. This can prevent others from using your API, so you can add your deployed front end app url to the list or you can use a
'*'
to allow anyone to connect to your app.
# Change this according to your needs:
ALLOWED_HOSTS = ['*']
If you haven't already done so, add
corsheaders
to the installed apps list:
INSTALLED_APPS = [
...
'corsheaders',
...
]
Configure whitenoise and cors by updating the settings.py file by updating the MIDDLEWARE list. The order matters here!:
MIDDLEWARE = [
# Add whitenoise right AFTER 'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
...
'corsheaders.middleware.CorsMiddleware',
# Add corsheader right BEFORE 'django.middleware.common.CommonMiddleware',
...
]
Configure the corsheaders package by adding one of the following. For more details about what these options do, take a look at the Configuration section in the doc. Make sure you clear your browser cache after setting up CORS in your back end to test if it is working.:
# To prevent access to your API from other applications add the
# CORS_ALLOW_ORIGINS list and include only your front end app's
# URLs (localhost and deployed). This list prevents a front end
# from connecting to your back end unless it comes from a listed origin:
CORS_ALLOWED_ORIGINS = [
"https://example.com",
"http://localhost:3000",
"http://127.0.0.1:3000"
]
OR
CORS_ALLOW_ALL_ORIGINS = True
The dj-database-url package parses a database URL to configure the connection string values (i.e., the database name, port, and root user and password) automatically. This allows us to configure our database connection string using the same format that Heroku uses when we create a Postgres database for our deployed app. Heroku automatically adds the DATABASE_URL to our config vars, which it reads as environment variables. The benefit for us is that we will be able to easily push to Heroku without having to make changes to our settings.py file. **Make sure to replace the entire
DATABASES
constant in your file:
DATABASES = {
'default': dj_database_url.config(conn_max_age=600)
}
The whitenoise package we installed is going to help us out with serving static files for our app such as
css
or image files. Even though you may be using Django REST Framework exclusively and didn't add any files of this type to the project yourself, the Django Admin site and Browseable API sites utilize static files like these extensively. If you don't tell Django where to store these files, your app won't deploy properly, so add a new constant to the bottom of yoursettings.py
file:
STATIC_ROOT=os.path.join(BASE_DIR, "static/")
- Add your environment variables to the
.env
file. You should already have copied over yourSECRET_KEY
from thesettings.py
file.
Add a MODE variable. We want the DEBUG value to be True when we're working locally, so set the value to
dev
here:
MODE=dev
Configure your database URL so that it is in the same format as the one that Heroku sets by adding a DATABASE_URL variable in the following format
DATABASE_URL=postgres://USER:PASSWORD@HOST:PORT/NAME
. Replace the USER, PASSWORD and database NAME with your project specific values. We'll use the default port for PostgreSQL on PORT 5432:
# DATABASE_URL=postgres://USER:PASSWORD@HOST:PORT/NAME
# Example: DATABASE_URL=postgres://petsuser:pets@localhost:5432/pets
-
Back in the Terminal, make sure ALL of your virtual environments are completely exited using the keyboard shortcut: ^ + D (control + D) or by typing
exit
. This is important because the environment variables you created are only loaded when you initially launch the environment. Once you've completely exited the shell, restart it withpipenv shell
and test that your app is working locally (python3 manage.py runserver
). If it is, proceed to the next steps: -
Run the Heroku commands to create your app. Make sure you're in the directory where the
manage.py
file is in your project when you run these commands:
Login:
heroku login
Create an app:
heroku create
Add Postgres
heroku addons:create heroku-postgresql:hobby-dev
Set your config vars on Heroku. Remember that the DATABASE_URL is already generated in the last step, so you'll just need to add the other environment variables from your .env file. Also don't forget to set MODE to prod (or production, something that is NOT called dev) and replace your secret key with your actual key 🙂 :
heroku config:set MODE=prod SECRET_KEY='your secret key'
- Run collectstatic in your virtual environment (this can take a few minutes the first time):
python3 manage.py collectstatic
- Add, commit and push:
git add .
git commit -m "Your message"
git push heroku master
- If your build is successful:
Run your migrations on Heroku.
heroku run python manage.py migrate
Create a superuser on your Heroku DB.
heroku run python manage.py createsuperuser