Grocery Bag using Django (Part-6) - Deployment on Heroku

Introduction

Till the last part, we had completed our web application starting from User Authentication to CRUD operations and date filtering. If you have missed any part, you can check out the blog series here. In this part (the final one), we're going to deploy our web app on Heroku.

According to Heroku-

Heroku is a cloud platform that lets companies build, deliver, monitor and scale apps — we're the fastest way to go from idea to URL, bypassing all those infrastructure headaches.

To deploy our app on Heroku, we need to make a few changes to our project. But first, you should create a free account on Heroku. Head over to heroku.com and create an account. Once you have created the account, you're ready to proceed.

Set up a Heroku app

Login to your Heroku account, and you'll be welcomed with a similar screen. Ignore the pywisher app.

Click on the New button and then click on Create new app. Enter the app name and then click on the Create app button. Make sure the name is available.

Click on the Settings tab, and scroll down to Buildpacks. Click on the Add buildpack button and add Python.

Since we'll require a database for this application, we are going to add a Postgres database (available for free on Heroku) in the resources. Click on the Resources tab and search for Postgres in the search box. Select Heroku Postgres in the search results, and then click on Submit order form to add it to the resources.

If you remember in the first part where we had set up our project, we had created some environment variables. We need to add them on Heroku too, as without them our app won't work at all. Click on the Settings tab and scroll to Config Vars and click on Reveal Config Vars. Open your .env file in the project and copy and paste it into your Config Vars as below:

Notice that we have set DEBUG to True for now, so that we can fix any bug we encounter during deployment. We'll change it to False later.

Set up Github Repository

We'll be deploying our application using Github, which will make our task easier. If you don't have a Github account, create one for yourself here. If you have a Github account, log in to your account. Once you login, you'll see a similar screen:

Click on the New button to create a new repository. Enter the repository name and click on Create repository. Once you create the repository, you'll be on a similar page:

Go to your project on your system. Make sure you have Git installed in your system. If not, install it from here. Open a terminal in your project and write the below commands:

$ git init
$ git remote add origin <your-repository-url-here>
$ git add .
$ git commit -m "Initial commit"
$ git push origin master

Replace the <your-repository-url-here>with the URL provided by Github. See the image below for reference:

Once you run the above commands, reload the page. You'll see a similar output.

Make changes to the project

First of all, we need to install a few dependencies in our virtual environment. Make sure you have activated it.

$ pip install gunicorn dj-database-url whitenoise psycopg2
  • Gunicorn is a Python WSGI HTTP Server for UNIX
  • dj-database-url will be used for getting database URL from the Heroku config vars.
  • whitenoise is used to serve static files
  • pyscopg2 is used for the Postgres database

Once you have installed the above dependencies, add them to a requirements.txt file. We can generate it automatically using the command:

$ pip freeze > requirements.txt

Next, create a runtime.txt file and add your Python version there as:

python-3.9.7

Also, create a .gitignore file and add the following content:

# Django #
*.log
*.pot
*.pyc
__pycache__
media
db.sqlite3

# Backup files # 
*.bak 

# If you are using PyCharm # 
.idea/**/workspace.xml 
.idea/**/tasks.xml 
.idea/dictionaries 
.idea/**/dataSources/ 
.idea/**/dataSources.ids 
.idea/**/dataSources.xml 
.idea/**/dataSources.local.xml 
.idea/**/sqlDataSources.xml 
.idea/**/dynamic.xml 
.idea/**/uiDesigner.xml 
.idea/**/gradle.xml 
.idea/**/libraries 
*.iws /out/ 

# Python # 
*.py[cod] 
*$py.class 

# Distribution / packaging 
.Python build/ 
develop-eggs/ 
dist/ 
downloads/ 
eggs/ 
.eggs/ 
lib/ 
lib64/ 
parts/ 
sdist/ 
var/ 
wheels/ 
*.egg-info/ 
.installed.cfg 
*.egg 
*.manifest 
*.spec 

# Installer logs 
pip-log.txt 
pip-delete-this-directory.txt 

# Unit test / coverage reports 
htmlcov/ 
.tox/ 
.coverage 
.coverage.* 
.cache 
.pytest_cache/ 
nosetests.xml 
coverage.xml 
*.cover 
.hypothesis/ 

# Jupyter Notebook 
.ipynb_checkpoints 

# pyenv 
.python-version 

# celery 
celerybeat-schedule.* 

# SageMath parsed files 
*.sage.py 

# Environments 
.env 
.venv 
env/ 
venv/ 
ENV/ 
env.bak/ 
venv.bak/ 

# mkdocs documentation 
/site 

# mypy 
.mypy_cache/ 

# Sublime Text # 
*.tmlanguage.cache 
*.tmPreferences.cache 
*.stTheme.cache 
*.sublime-workspace 
*.sublime-project 

# sftp configuration file 
sftp-config.json 

# Package control specific files Package 
Control.last-run 
Control.ca-list 
Control.ca-bundle 
Control.system-ca-bundle 
GitHub.sublime-settings 

# Visual Studio Code # 
.vscode/* 
!.vscode/settings.json 
!.vscode/tasks.json 
!.vscode/launch.json 
!.vscode/extensions.json 
.history

This tells Git to ignore these files.

Go to the Settings tab on Heroku and grab your Heroku app URL from here:

Remove the https:// and slash(/) from the URL. For example, my URL is: https://grocery-bag-ashutosh.herokuapp.com/.After the change, my URL looks like this: grocery-bag-ashutosh.herokuapp.com.

Open the GroceryBag/settings.py file and add this URL in the ALLOWED_HOSTS list as:

DEBUG = config('DEBUG', default=False, cast=bool)

ALLOWED_HOSTS = ['127.0.0.1', 'localhost', 'grocery-bag-ashutosh.herokuapp.com']

Add the Whitenoise middleware to the MIDDLEWARE list as:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    # Add Whitenoise middleware here
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Notice that the whitenoise middleware have been included right after the django.middleware.security.SecurityMiddleware

Next, update the database configurations right after the DATABASES dictionary as:

import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)

Also, update the STATIC_ROOT as:

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles' # Add this line

STATICFILES_DIRS = [
    BASE_DIR / "static",
]

Create a Procfile in the root directory of the application and add the following line:

web: gunicorn GroceryBag.wsgi --log-file -

This declares a single process type, web, and the command needed to run it. The name web is important here. It declares that this process type will be attached to the HTTP routing stack of Heroku, and receive web traffic when deployed. Notice that the Procfile file doesn't have any extension.

Now, we have done enough changes and we are ready to commit and push it to the Github repository using the commands:

$ git add .
$ git commit -m "Ready for deployment"
$ git push origin master

Deploy on Heroku

Now we're completely ready to deploy our app on Heroku. Open the Heroku app and click on the Deploy tab. In the Deployment method on the page, choose Github. Search for your repository and click on Connect to select it.

Once it is connected successfully, you'll see a button called Deploy branch. Click on the button and the deployment process will start:

Heroku will install all the dependencies mentioned in the requirements.txt file and will use the Python version mentioned in the runtime.txt file. After the process is completed, you will see a success message as this:

Our app has been deployed successfully!!

But there's one step still left. If you remember, whenever we made any changes to the database, we needed to migrate the database. Similarly here also, we need to migrate the database. Click on More and then on Run Console to run bash:

Once you click on that, you'll find a text box. Write the below command there:

Once you run the command, you'll see the database migrations happening. With this, your app has been deployed successfully and you're ready to test it!

Testing our app

Click on Open app button to view the app:

Conclusion

This was the final blog in this series where we have successfully deployed our app. You can find all the blogs in this series: https://iread.ga/series/11/grocery-bag-application-using-django

If you have any questions, feel free to comment below!

23