Auto deploy Django projects on Heroku using GitHub repository

Muhammad Abdullah Mughal
9 min readDec 16, 2021

This article addresses followings

  • Create a simple Django project
  • Upload project on git repository
  • Create app on Heroku server
  • Configure git repo with Heroku
  • Add dependencies and modify configuration of Django project for Heroku Cloud
  • Set pipeline for auto deployment on Heroku server for each git push

Without further ado,

Quick Review

Followings are end products of this story,

Django Project & App

We are working with windows os, except some commands rest will be same on both windows & Linux machine.

1. Preparing Environment

Python version, let’s start by checking the installed version of python, I am currently working with python3 (version 3.10.0). You can check the version by entering the python -V command on the terminal / console. This code can work on python3 versions.

C:\Users\abdullah\python>python -V
Python 3.10.0

Virtual environment, execute python -m venv env command on terminal to create a virtual environment. This command will create a virtual environment in the current directory location.

C:\Users\abdullah\python>python -m venv env
C:\Users\abdullah\python>dir
Volume in drive C has no label.
Volume Serial Number is 8C8F-7182
Directory of C:\Users\abdullah\python
16/12/2021 08:53 PM <DIR> .
16/12/2021 08:53 PM <DIR> ..
16/12/2021 08:53 PM <DIR> env
0 File(s) 0 bytes
3 Dir(s) 72,877,871,104 bytes free

Activate virtual environment, after creating a virtual environment, execute the following commands to activate the virtual environment.

  • Windows OS command env\Scripts\activate
C:\Users\abdullah\python>env\Scripts\activate
(env) C:\Users\abdullah\python>
  • Linux OS command source env/bin/activate
source env/bin/activate
(env) $

2. Setting Up Django

Installation via pip, Execute python -m pip install django command in terminal and install Django in newly created virtual environment.

(env) C:\Users\abdullah\python>python -m pip install django
Collecting django
Downloading Django-4.0-py3-none-any.whl (8.0 MB)
|████████████████████████████████| 8.0 MB 22 kB/s
Collecting asgiref<4,>=3.4.1
Using cached asgiref-3.4.1-py3-none-any.whl (25 kB)
Collecting tzdata
Downloading tzdata-2021.5-py2.py3-none-any.whl (339 kB)
|████████████████████████████████| 339 kB 20 kB/s
Collecting sqlparse>=0.2.2
Using cached sqlparse-0.4.2-py3-none-any.whl (42 kB)
Installing collected packages: tzdata, sqlparse, asgiref, django
Successfully installed asgiref-3.4.1 django-4.0 sqlparse-0.4.2 tzdata-2021.5
WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available.
You should consider upgrading via the 'C:\Users\abdullah\python\env\Scripts\python.exe -m pip install --upgrade pip' command.

(env) C:\Users\abdullah\python>

Starting Project, Once the django library is installed we can create a django project by using command django-admin startproject djheroku_project you can use your own project name instead of djheroku_project.

(env) C:\Users\abdullah\python>django-admin startproject djheroku_project
(env) C:\Users\abdullah\python>

Following will be the structure of djheroku_project after executing the command.

(env) C:\Users\abdullah\python>tree djheroku_project /A /F
Folder PATH listing
Volume serial number is 8C8F-7182
C:\USERS\ABDULLAH\PYTHON\DJHEROKU_PROJECT
| manage.py
|
\---djheroku_project
asgi.py
settings.py
urls.py
wsgi.py
__init__.py


(env) C:\Users\abdullah\python>

Execute python djheroku_project\manage.py runserver command to check django project is running successfully.

(env) C:\Users\abdullah\python>python djheroku_project\manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
December 16, 2021 - 21:50:16
Django version 4.0, using settings 'djheroku_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

Django web interface, Open http://127.0.0.1:8000 in the browser to check if the Django project is installed successfully.

Django project running on localhost
Django project running on localhost

Creating Django App, Let’s change the directory and move into the newly created project’s directory and execute python manage.py startapp example command in the root of django start project. You can use your own app name instead of example.

(env) C:\Users\abdullah\python>cd djheroku_project
(env) C:\Users\abdullah\python\djheroku_project>python manage.py startapp example
(env) C:\Users\abdullah\python\djheroku_project>

Following is structure of example Django app

(env) C:\Users\abdullah\python\djheroku_project>tree example /A /F
Folder PATH listing
Volume serial number is 00000066 8C8F:7182
C:\USERS\ABDULLAH\PYTHON\DJHEROKU_PROJECT\EXAMPLE
| admin.py
| apps.py
| models.py
| tests.py
| views.py
| __init__.py
|
\---migrations
__init__.py

Configure App with Project, Open settings.py file Django Project’s root directory and add app name example in INSTALLED_APPS list.

Adding Django app `example` in Project’s INSTALLED_APPS

Modifying App For Static Resource Usage

To make things more clear I will be adding an image, css file in the app’s html home page. You can extend it by adding multiple resources as per need so the following are additions in code.

Adding html sources in app

  • Created a folder named templates in example app folder
  • Added an index.html file in templates folder
djheroku_project/example/templates/Index.html

Addition of image & css file

  • Created a folder named static in example app folder
  • Added two more folders named as css & images, both folders contain a css file and an image file which are used in index.html.

View For Index html, adding function in views.py in example app to render a index.html template upon request.

djheroku_project/example/views.py

URL config for view, To view the index.html, we need to configure the URL in urls.py so that we can show our template upon the URL hit. For basic understanding I have configured the index template on default address.

djheroku_project/djheroku_project/urls.py

Django Project & App Ready

Our single page Django app is ready upon python manage.py runserver following web page can be observed on the web browser.

Freezing Requirements, Now execute python -m pip freeze > requirements.txt command to pin all used dependencies

(env) C:\Users\abdullah\python\djheroku_project>python -m pip freeze > requirements.txt

(env) C:\Users\abdullah\python\djheroku_project>

3. GitHub Repo

Install Git on local system & create free account on GitHub. Once you are sign in to account then move to next step,

Create a repository, click on New repository

Create a repository on GitHub
Create a repository on GitHub
  • Provide a Repository name and hit Create Repository.
Provide repository name and hit create
Provide repository name and hit create
  • Once repository is created we can push our code in it.
Interface of newly created repository
Interface of newly created repository

Add & configure ssh / pgp keys on local system for commits, follow official documents

Commit local code and push on GitHub

(env) C:\Users\abdullah\python\djheroku_project>git init
Initialized empty Git repository in C:/Users/abdullah/python/djheroku_project/.git/
(env) C:\Users\abdullah\python\djheroku_project>

Execute git add . command on project’s root folder

(env) C:\Users\abdullah\python\djheroku_project>git add .(env) C:\Users\abdullah\python\djheroku_project>

Add commit using git commit -m “initial commit”

(env) C:\Users\abdullah\python\djheroku_project>git commit -m "initial commit"
[main (root-commit) b612cb9] initial commit
29 files changed, 778 insertions(+)
create mode 100644 .gitignore
create mode 100644 db.sqlite3
create mode 100644 djheroku_project/__init__.py
create mode 100644 djheroku_project/__pycache__/__init__.cpython-310.pyc
create mode 100644 djheroku_project/__pycache__/settings.cpython-310.pyc
create mode 100644 djheroku_project/__pycache__/urls.cpython-310.pyc
create mode 100644 djheroku_project/__pycache__/wsgi.cpython-310.pyc
create mode 100644 djheroku_project/asgi.py
create mode 100644 djheroku_project/settings.py
create mode 100644 djheroku_project/urls.py
create mode 100644 djheroku_project/wsgi.py
create mode 100644 example/__init__.py
create mode 100644 example/__pycache__/__init__.cpython-310.pyc
create mode 100644 example/__pycache__/admin.cpython-310.pyc
create mode 100644 example/__pycache__/apps.cpython-310.pyc
create mode 100644 example/__pycache__/models.cpython-310.pyc
create mode 100644 example/__pycache__/views.cpython-310.pyc
create mode 100644 example/admin.py
create mode 100644 example/apps.py
create mode 100644 example/migrations/__init__.py
create mode 100644 example/migrations/__pycache__/__init__.cpython-310.pyc
create mode 100644 example/models.py
create mode 100644 example/static/css/style.css
create mode 100644 example/static/images/maxresdefault.jpg
create mode 100644 example/templates/index.html
create mode 100644 example/tests.py
create mode 100644 example/views.py
create mode 100644 manage.py
create mode 100644 requirements.txt

Execute git push command to push code in GitHub

(env) C:\Users\abdullah\python\djheroku_project>git push --set-upstream origin main
Enumerating objects: 38, done.
Counting objects: 100% (38/38), done.
Delta compression using up to 4 threads
Compressing objects: 100% (34/34), done.
Writing objects: 100% (38/38), 44.45 KiB | 3.17 MiB/s, done.
Total 38 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), done.
To https://github.com/iAbdullahMughal/djheroku_project.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

(env) C:\Users\abdullah\python\djheroku_project>

4. Heroku Cloud
Create a free account on Heroku cloud using their official guide https://signup.heroku.com/

Now login into your heroku account and open https://dashboard.heroku.com/apps.

Create new app, Click on new & then click on Create new app

Create new app dialogue on Heroku Cloud
Create new app dialogue on Heroku Cloud

Provide app name and click on Create app

Heroku app name wizard
Heroku app name wizard

Once the app create you will be redirected to the app’s dashboard.

Connect GitHub with Heroku, Click on GitHub button in front of Deployment method, Once dropdown menu is opened click on Connect to GitHub

Connect GitHub with Heroku — Heroku Dashboard
Connect GitHub with Heroku — Heroku Dashboard

Allow Heroku app to access, your GitHub public repositories.

Connect GitHub Repo with Heroku App, Once GitHub is configure, search repository using search bar, once repository is listed press connect button.

GitHub repository is listed on Heroku App Dashboard
GitHub repository is listed on Heroku App Dashboard

Now click on Enable Automatic Deploys and select the branch that you want to deploy. For the tutorial I am leaving the main deploy branch. Press Deploy Branch.

Deploy Django repo on Heroku cloud from main branch
Deploy Django repo on Heroku cloud from main branch

😞 Heroku app failed to deploy (Expected)

Our first Deploy will be failed and following error will appear on Heroku logs.

Django project failed to deploy first time on Heroku
Django project failed to deploy first time on Heroku

Now we need some tweaks in our Django project to make it compatible with Heroku cloud.

Django & Heroku Configuration Dependencies

Additional dependencies, we need to add & install gunicorn, whitenoise and django-heroku in requirements.

python -m pip install gunicorn
python -m pip install whitenoise
python -m pip install django-heroku

After adding these dependences our requirements.txt looks like this

Updated requirements.txt file

Modifying settings.py, after adding these dependencies we need to update some configurations in settings.py

STATIC_ROOT & STATICFILES_DIRS configurations in settings.py

Add static folder in project root, To enable Heroku to copy static files like images, js, css we will create a folder in project root.
This folder will contain an empty file with .keep name, so the folder can be stored on git and copied on Heroku cloud.

Static folder with empty file named .keep in root of Django project folder
Static folder with empty file named .keep in root of Django project folder

Adding Procfile, will add an additional file named Procfile, although heroku knows our application is Django python but we will add this file to guide Heroku worker to perform actions as per our instructions and requirements. Content of Procfile

web: gunicorn djheroku_project.wsgi

Git add and pushing to main branch, repeat steps for get add, commit and main push,

(env) C:\Users\abdullah\python\djheroku_project>git commit -m "Adding support for heroku cloud"
.
.

.
(env) C:\Users\abdullah\python\djheroku_project>git commit -m "Adding support for heroku cloud"
(env) C:\Users\abdullah\python\djheroku_project>git push --set-upstream origin main

Once code is update in GitHub, a worker is started on Heroku Cloud to install Django app. After adding above configuration build was successful and Django application started running.

Heroku build logs for second check in
Heroku build logs for second check in

Django App Running On Heroku Cloud

Simple Django app running on Heroku — https://djheroku-project.herokuapp.com/
Simple Django app running on Heroku — https://djheroku-project.herokuapp.com/

Our Django based simple application is now live at https://djheroku-project.herokuapp.com/.

Isn’t it fun

Go ahead, build and deploy your django app free on heroku server.

I hope this article has helped you to learn something new, if I have missed anything or you need more help feel free to post questions or send DMs.

📝 some notes ,

  1. This tutorial is intended to show how to configure django, heroku and github
  2. Please make sure that your app and data is secure, if not please secure it accordingly
  3. Whole article is for educational purposes.

Have a good day

--

--

Muhammad Abdullah Mughal
0 Followers

Knows a bit of hacking, OSINT Analyst, Cybersecurity Analyst, Malware Researcher, Automation engineer, Code Enthusiast and full stack developer 🕵🏼