Deploying your Django Site to Heroku

Heroku is a highly preferred platform to host Simple to Complex Web Applications. It supports a wide array of Frameworks giving you extensive scalability.

Hosting your Web App on Heroku gives you the freedom to perfect your Web App rather than worrying about the platform that it is hosted on.

The below post explores the several steps to follow in hosting your Django Site to Heroku. The list may seem exhaustive at first but will start to become a cake walk once you manage to host your first application.

Applies to Mac: OS X 10 and above

Create a Heroku Account

Visit heroku.com and create an account

Download the Command Line Interface. Using the command line interface gives you incredible features setup your web application using simple scripts.

Open Terminal and from within your Project Directory,  login to your heroku account using the below command.

$ heroku login

The browser will open a prompt you to login. Successful login will enable you to continue working from the command line.

Create your Heroku Web App

$ heroku create myfirstwebapp

If available, a domain myfirstwebapp.herokuapp.com will be created instantly. If already used, it will prompt you to enter an alternate name.

$ heroku open

This will open your newly created web app in the browser

Install gunicorn in your Django Project

Green Unicorn (unicorn) is a Web Server Gateway Interface (WSGI) server implementation that will help you package and run your Python Web Application.

$ pip install gunicorn

Compile List of Libraries

You can package the list of libraries pertaining to your specific Django Project. Compiling a list enables these libraries to also be installed on your heroic app at the time of deployment.

$ pip freeze > requirements.txt

The above command will create a requirements.txt file in the root folder of your Project. Please inspect this file.

If your Project is created in a virtual environment, it would only list Libraries pertaining to the specific project. But if it is created within your computers version of Python, it would list all the libraries. You may then have to manually remove unnecessary libraries from requirements.txt file that do not pertain to your Django Project.

Creating a Process File

A Process File (Procfile) is a mechanism for declaring what commands are run by your web applications containers on the platform. In this case, our platform is heroku. The Procfile can be used to declare multiple process types.

Create a filed named Procfile in the root directory of your Django Project.

web: gunicorn projectname.wsgi
  • web:, this is the process type which will receive web traffic when deployed
  • gunicorn, command needed to run the web process. In short, it allows the python code talk to the web server.
  • projectname, replace this your Django Project Name. This is the name of the directory that contains the settings.py file.

Adding the Host

Under settings.py add the hostname of your heroku project under ALLOWED_HOSTS

ALLOWED_HOSTS = ['myfirstwebapp.herokuapp.com']

Installing Git

Git is a distributed open source source control (also referred to as “version control”) system commonly used to track and manage file changes. Git is the preferred version control system for Python projects.

Git will aid in managing the file changes in our Local Django Web App and help to write them to our Heroku Site with ease.

Run the below git commands from the Terminal

$ git init

The above command creates an empty local repository within your project folder that will manage all changes to your project files.

But all the files in our Project folder are not required to be pushed to the Live Deployment. For this we will create a file named .gitignore that will address the list of files to be excluded.

Create a file named .gitignore in your Project root directory and copy the contents from the link provide below. When you review the list of files, you will also notice that we ignore the db.sqlite3 as well. The Live App will use the PostgreSQL instead and hence we do not need the SQLite database.

Link to .gitnore list for Python

For Mac machines, add the below line as well to the .gitignore file

.DS_Store

Let us now use git to see which files will be added to your Live Deployment (git status).

$ git status
$ git add -A
$ git commit -m "Initial Project Compilation"

The git add command adds a change in the working directory. It basically tells Git that you want to include updates to a particular files or files in the next commit. Option -A, refers to all files.

The git commit command is used to save your changes to the local repository that we had created initially.

Push to Live Deployment

git push heroku master

If your application does not use any static files (example: Local  CSS Files, Images etc), it should successfully get deployed without any errors from the local machine.

heroku open

Though the deployment was successful without errors, the Web App will return an error as there is no database configured on heroku.

Installing PostgreSQL Database on Mac

Download Link

Instructions for Installation

Kindly ensure that you follow all the 3 Steps in the Installation procedures including adding the $Path to the environment variable.

Creating PostgreSQL Database on heroku

By default, your heroku app comes with a pre-installed PostgreSQL. Running the below command will list the pre-installed database and other pre-instaleld add ons if any.

heroku addons

If you wish to create your own database, use the below command

$ heroku addons : create heroku-postgresql : hobby-dev

hobby-dev refers to the Free Plan under your heroku account

$ heroku pg

The above command will display details of your PostgreSQL database.

Seamless Deployment and Development Experience

For a seamless deployment and development experience, you will need to install the django-heroku library to your Django Project.

$ pip install django-heroku

If the above command returns an error, kindly ensure that you have your environment variables correctly configured while installing PostgreSQL.

Updating requirements.txt

Since a new library has now been installed (django-heroku), you must update the requirements.txt file with the new Library Name and Version

$ pip freeze > requirements.txt

Updating settings.py

Add the below commands to your settings.py file

$ import django_heroku
$ django_heroku.settings(locals())

This will automatically configure Database URL, Allowed Hosts and enable accessibility to your Static Files among other benefits.

Creating Tables on your Live PostgreSQL Database

heroic run python manage.py migrate

Deployment Checklist

Django recommends some important measures before your deploy your Web Application. Make sure to deploy most of them if not all the recommendations listed.

Django Deployment Checklist

First Release of your Web Application

$ git status
$ git add -A
$ git commit -m "First Release of Web App"
$ git push update master

Your Django Web Application should now be ready to use and share.

Advertisements

Tkinter TreeView – Enable Sorting upon Clicking Column Headings

The below code snippet can help you achieve the Sorting Option on Treeview Column Headings in Tkinter in both ascending and descending order.

columns = ("Student","Course","Last Session")

tv = Treeview(popup, show='headings', columns=columns,height=25)

def treeview_sort_column(tv, col, reverse):
    l = [(tv.set(k, col), k) for k in tv.get_children('')]
    l.sort(reverse=reverse)

    # rearrange items in sorted positions
    for index, (val, k) in enumerate(l):
        tv.move(k, '', index)

    # reverse sort next time
    tv.heading(col, command=lambda _col=col: treeview_sort_column(tv, _col, not reverse))

for col in columns:
    tv.heading(col, text=col,command=lambda _col=col: treeview_sort_column(tv, _col, False))
tv.pack()

 

ModuleNotFoundError: No module named ‘babel.numbers’

Traceback (most recent call last):
File "tkinter/__init__.py", line 1705, in __call__
File "script.py", line 726, in
File "script.py", line 536, in calendar
File "tkcalendar/calendar_.py", line 211, in __init__
File "babel/dates.py", line 314, in get_day_names
File "babel/core.py", line 641, in days
File "babel/core.py", line 364, in _data
File "babel/localedata.py", line 111, in load
File "babel/localedata.py", line 111, in load
File "babel/localedata.py", line 117, in load
ModuleNotFoundError: No module named 'babel.numbers'

Solution Explained

Locate the tkcalendar folder under venv/lib/python3.x/site-packages of your project folder.

Under calendar.py, add an additional import for the missing module.

import calendar
from babel.dates import format_date, parse_date, get_day_names, get_month_names
from babel.numbers import *  # Additional Import

Mac OS X – ValueError: unknown locale: UTF-8

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/locale.py", line 568, in getdefaultlocale
return _parse_localename(localename)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/locale.py", line 495, in _parse_localename
raise ValueError('unknown locale: %s' % localename)
ValueError: unknown locale: UTF-8

To Solve the above issue you will need to add the below variables in your .profile or .bash_profile

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

From the Launchpad, open the Terminal

Type nano .profile
Nano is an easy to use editor

Copy the below lines of code
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

Press Ctrl+O to save the lines
Press Return to Save
Press Ctrl+X to Exit

To verify that the variables have been added to the .profile, use the below code in the terminal

open -e .profile

Try running your program once again. If the issue has not been resolved, use the same approach with the file .bash_profile

 

gspread timeout – Reconnecting to the Google API

gspread loses connection with the Google API probably every 10 minutes. This can be easily tackled by calling a function or Class which reconnects to the database.

import gspread
from oauth2client.service_account import ServiceAccountCredentials

from datetime import datetime
from datetime import timedelta

def connect_database():

scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name('client_secret.json', scope)
client = gspread.authorize(creds)

workbook1 = client.open("File_Name")
w1 = workbook1.worksheet("Sheet1")
w2 = workbook1.worksheet("Sheet2")

return w1,w2

program_start_time=datetime.now()

if datetime.now() > program_start_time + timedelta(minutes=10):
worksheet1, worksheet2 = connect_database()
program_start_time = datetime.now() #Resets the Program Start Time