My Django Heroku Checklist
Tags: python, heroku, webdev
Published: 2022-02-05 03:18:51

A lot of articles seem to be different from what Heroku's documentation provides, and even with Heroku's documentation I had a little bit of trouble on my last deployment. I decided I'd create a checklist for my deployment as a baseline to work with.

This is a working document and not currently meant to serve as a How-To or guaranteed to be exhaustive/bug free, but rather give myself a centralized set of steps to draw from.

- Ensure any secret keys are outside of git repo, scrub them from history if needed and store in .env file. 
  + Its good practice to never commit these, but if you did [BFG-repo-cleaner](https://rtyley.github.io/bfg-repo-cleaner/) gets the job done.
  + I use python-dotenv to access environment variables. [python-dotenv documentation](https://github.com/theskumar/python-dotenv)

- In `settings.py` set DEBUG to False, Set ALLOWED_HOSTS and CORS_ALLOWED_ORIGINS (if running front end from a separate deployment)

```python

DEBUG = False
ALLOWED_HOSTS = ['your-app-name.herokuapp.com']
CORS_ALLOWED_ORIGINS = ['https://your-frontend-app-name.herokuapp.com']

```
- ~~Run `python manage.py collectstatic` to collect static files. Not doing this will cause a server 500 error.~~ Heroku will run collectstatic during build.


- Install gunicorn, whitenoise, cloudinary, django-cloudinary-storage (we install the cloudinary apps if using uploaded media) and add to requirements.txt

```
pip install gunicorn whitenoise cloudinary
pip freeze > requirements.txt
```

- Add Procfile to root folder with following contents:

```bash
web: gunicorn myProjectName.wsgi
```
myProjectName will be identical to the name of the folder that contains your settings.py and wsgi.py file

- Add whitenoise to middleware in settings.py and ensure settings are properly set. According to http://whitenoise.evans.io/en/stable/django.html# whitenoise middleware should be listed immediately after Django's security middleware, before all other middleware.
```
MIDDLEWARE = [
  'django.middleware.security.SecurityMiddleware',
  'whitenoise.middleware.WhiteNoiseMiddleware',
  # ...
]

# According to whitenoise docs, we must specify a STATIC_ROOT
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
```
If we're using uploaded media, we can use Cloudinary for hosting for said media
https://devcenter.heroku.com/articles/cloudinary#using-with-django

https://pypi.org/project/django-cloudinary-storage/#requirements

Add Cloudinary to installed apps and config details. The docs say to put cloudinary_storage above `django.contrib.staticfiles` but that gave me build errors, probably because cloudinary says to do things differently if you are using their hosting for static, media, or both.

```python
INSTALLED_APPS = [
'cloudinary',
'cloudinary_storage',
# other apps
]

""" 
I'm storing these keys in local .env for local testing, 
but don't forget to add these keys to your Heroku environment
variables so that it can populate these values when running live.
""" 

CLOUDINARY_STORAGE = {
    'CLOUD_NAME' : str(os.getenv('CLOUDINARY_CLOUD_NAME')),
    'API_KEY' : str(os.getenv('CLOUDINARY_API_KEY')),
    'API_SECRET' : str(os.getenv('CLOUDINARY_API_SECRET'))
}
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'

```

- Install Django-Heroku
https://devcenter.heroku.com/articles/django-app-configuration

```
pip install django-heroku
```
Add the following import statement to the top of settings.py:

```python
import django_heroku
...
```

Then add the following to the bottom of settings.py:

```python
# Activate Django-Heroku.
django_heroku.settings(locals())
```

- Follow instructions to deploy via Heroku CLI or GitHub
    - I had a problem once where Heroku wasn't properly installing dependencies including gunicorn. Removing pipfile and providing only requirements.txt seemed to solve this. I'm not actually sure where the pipfiles came from since I used virtualenv and not pipenv to create my virtual environment, and I could only find docs of pipfile coming from pipenv.

You may need to run migrations once the application is deployed in order for the application to work. Access your app's developer console through Heroku (currently accessible via the "More" button next to the "Open App" button on the dashboard) and run 

`python manage.py make migrations`
`python manage.py migrate`


[Part 2 about deploying with a React Front-end here](https://dev.to/thomz/my-djangoreact-heroku-deployment-checklist-d9f)