🎯 Tutorial: Deploying a Django app on Heroku
Tags: heroku, deploy, devops, django
Published: 2021-02-18 04:07:06

# Deploying a Django App

Deploying a Django application to the internet could be difficult, but there are free and dedicated  hosting platforms designed for deploy specific frameworks to the Internet.

Heroku may be the perfect choose for those how want a starting free web hosting and sub-domain, and an easy configurable hosting.

## Pre-requirements:
* You need to have *Heroku CLI* installed, and be logged in to your account. 
If you don't have it installed, check out the official docs, [Here](https://devcenter.heroku.com/articles/heroku-cli)

Now that you have it installed and you are logged in, you can continue with the Python stuff 🐍.

## Necessary packages to deploy on Heroku:

Now make sure to create a virtual environment, my preferred way is `virtualenv`:
First install it with `pip install virtualenv`, create a virtual env and create it:

```python
virtualenv venv

#then 
source venv/bin/activate

# Depending on your shell, you could run a different command.
```
Install Django and your Python development tools:

```python
pip install django
```
You need some packages to deploy an application to heroku, so let's get into it:

If you just want a command to install most packages you need, copy the line below:

```python
pip install gunicorn django-heroku python-decouple
```

Let's start with the package that handles most of the server  operations: [Gunicorn](https://gunicorn.org/) is an easy yet powerful Python HTTP server.

```python
pip install gunicorn
```
Django Heroku, allow us to don't worry of our settings in the Heroku server.

```python
pip install django-heroku
```
This package comes with other important packages that facilitates us the deployment in the fields, of static files `whitenoise`, a postgreSQL adapter `psycopg`, a package that helps to connect with the Database `dj-database-url`, and django-heroku itself.

This is almost everything but only a package is left 😁 :
```python
pip install python-decouple
```
This package helps us to pass python environmental variables on Django, we will se it later I promise😊.

Now let's run `pip freeze`, you should get something like this:

```python
asgiref==3.3.1
dj-database-url==0.5.0
Django==3.1.6
django-heroku==0.3.1
gunicorn==20.0.4
psycopg2==2.8.6
python-decouple==3.4
pytz==2021.1
sqlparse==0.4.1
whitenoise==5.2.0
```
Run this command to create a `requirements.txt` file that Heroku will use to install of the packages needed.

```python
pip freeze > requirements.txt  
```

## Create a Procfile

```python
# Run this in the root directory of the app
touch Procfile
```
Open the file and copy the following file:

```
web: gunicorn (Your app).wsgi
```

This tells Heroku, that it must run a web process, with gunicorn as HTTP server and with a `wsgi` file located in `(Your app)`. Remember to change `(Your app)` with the name of your project.

## Settings.py file

We just installed a lot of stuff, but now it's time to apply all of this in the `settings.py` file, but first Pro tip.

### **Pro Tip:**

Before continuing modifying the settings file, do the following things:

Duplicate the `settings.py` file of your project, and rename it as `settings_local.py`,you will leave that file untouched, and use that configuration, while developing the application in local.

To run the server with the local settings just run the following command:

```python
python manage.py runserver --settings=(Your app).settings_local
```

Now after that, continue configuring the production environment.

## Modifying the settings:
### Importing modules
At the top of the file import the following modules:

```python
# Import to serve staticfiles correctly
import os
import django_heroku
import dj_database_url
from decouple import config
```
### Static files
In the `MIDDLEWARE` variable, set whitenoise middleware below  the Security Middleware:

```python
MIDDLEWARE = [
  # 'django.middleware.security.SecurityMiddleware',
  'whitenoise.middleware.WhiteNoiseMiddleware',
  # ...
]
```
Now go to the bottom of the app, where you could find the following commentaries:

```
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
```
Below paste this code🖥️:

```python
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]

STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

```

Perfect, now our static files should be managed by Whitenoise.

### Last step
At the very bottom of the file set the django heroku settings

```python
django_heroku.settings(locals())
```
That's all of you need to deploy an app to Heroku, good luck!

## Create a Pipeline, from a Github Repository

Login or Create an account on Heroku, go to dashboard and click in the *New Button*.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wlq4tszzj9q9hw2lv35p.png)
 

Now click on create a new pipeline:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l67rvtzr0rtbud9u0z8n.png)

After that you will be redirected, to the pipeline, click on the add app button in order to create a new app.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9styves30pt0crhcaort.png)

Click and add your new app.


![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1ubon18g6l61yuboe3a.png)
  
 
From now you will get a fully featured dashboard with the app.

Go to Deploy tab, and in the bottom you will get a button where you can deploy your app. Now click on that button and deploy the main branch.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzc2sq3x4gbtrjv069y1.png)



## Extra:
### Troubleshooting:

Probably you will get a lot of errors before you can publish your app to the internet, so I'm going to tell you the most common problems and how to fix them.

### Static files errors:

One of the most common errors that you will get, may be related with static files.

#### Error:
```python
-----> $ python manage.py collectstatic --noinput
       Post-processing 'css/owl.carousel.min.css' failed!
       Traceback (most recent call last):
         File "manage.py", line 22, in <module>
           main()
         File "manage.py", line 18, in main
           execute_from_command_line(sys.argv)
         File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
           utility.execute()
         File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 395, in execute
           self.fetch_command(subcommand).run_from_argv(self.argv)
         File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 330, in run_from_argv
           self.execute(*args, **cmd_options)
         File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 371, in execute
           output = self.handle(*args, **options)
         File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 194, in handle
           collected = self.collect()
         File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 138, in collect
           raise processed
       whitenoise.storage.MissingFileError: The file 'css/owl.video.play.png' could not be found with <whitenoise.storage.CompressedManifestStaticFilesStorage object at 0x7fab586a2710>.
       The CSS file 'css/owl.carousel.min.css' references a file which could not be found:
         css/owl.video.play.png
       Please check the URL references in this CSS file, particularly any
       relative paths which might be pointing to the wrong location.
 !     Error while running '$ python manage.py collectstatic --noinput'.
       See traceback above for details.
       You may need to update application code to resolve this error.
       Or, you can disable collectstatic for this application:
          $ heroku config:set DISABLE_COLLECTSTATIC=1
       https://devcenter.heroku.com/articles/django-assets
 !     Push rejected, failed to compile Python app.
 !     Push failed
```
As you can see, the error is caused because of a css file pointing to another file that doesn't exist.

Heroku and Django are very sensitive with static files so if a pointing file doesn't exist, an error will occur.

To fix this particular error, set the environment key, `DISABLE_COLLECTSTATIC` and run locally the `collectstatic` command.

```python
# Root directory
heroku config:set DISABLE_COLLECTSTATIC=1

# collect static

python manage.py collectstatic
```
Push the code and deploy the app, this problem should be solved.

### Fixing other errors:

To fix an error in production, We will use a logger in Django.

Paste the code below, this will give you a Django logger in production, which you can access with the following command.

```python
# Django logger

# Debugging in heroku live
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': ('%(asctime)s [%(process)d] [%(levelname)s] ' +
                       'pathname=%(pathname)s lineno=%(lineno)s ' +
                       'funcname=%(funcName)s %(message)s'),
            'datefmt': '%Y-%m-%d %H:%M:%S'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        }
    },
    'handlers': {
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        }
    },
    'loggers': {
        'testlogger': {
            'handlers': ['console'],
            'level': 'INFO',
        }
    }
}

DEBUG_PROPAGATE_EXCEPTIONS = True
COMPRESS_ENABLED = os.environ.get('COMPRESS_ENABLED', False)

# Heroku logs
heroku logs --tail
```

Now you will get a real time logger to debug your application on production.

Thanks for your time hopefully this tutorial will be useful for you 🤗. 

>Follow me in [My blog](https://developerroad.herokuapp.com/blog/), 
 to get more awesome tutorials like this one.
 Please consider supporting me on [Ko-fi](https://ko-fi.com/daniel1404) you help me a lot to 
 continue building this tutorials!.
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y03P8P1)