Deploying Django to Heroku with PostgreSQL database is simple but we’ll miss some simple stuff and stuck.
This article demystify those into simple steps.
Initial Installation and setup
Before changing any files we need to install require packages.
Modules for development setup
Decople and Psycopg2
pip install python-decouple
pip3 install psycopg2
Decouple module helps us to handle the environment variables for the local development
PostgreSQL database adaptor for python.
Heroku modules
Following modules are Heroku dependent gunicorn, django-heroku, whitenoise, dj-database-url
white noise used to serve the static contents in Heroku and gunicorn is a application server for django in Heroku.
pip install gunicorn
pip install django-heroku
pip install whitenoise
pip install dj-database-url
Environment variables
create .env in root folder(where manage.py is there) location. Add the database configuration, secret key and and debug
DATABASE_NAME = 'interview'
DATABASE_USER = 'postgres'
DATABASE_PASSWORD = 'admin@1234'
DATABASE_HOST = '127.0.0.1'
DATABASE_PORT = '5432'
SECRET_KEY= 'your-secret-key'
DEBUG = True
create gitignore file to avoid committing system credentials and unwanted files
create .gitignore in root folder add below lines to it
.env
*.pyc
Now initial setup is done we need to change our application configuration to make it run.
1. settings.py
First we need to modify the settings.py separating setting settings will another article(base, development, production). To make it simple these change will be in single file.
Change the debug, secret-key, database config, static from from settings.
from decouple import config, UndefinedValueError
import config on top
Update the debug and secret key
try:
DEBUG = config('DEBUG')
except UndefinedValueError:
DEBUG = False
Allowed Host
If debug is false allowed host to added . Add Heroku server URL in the end if you want specific host to be allowed either allowed any host
ALLOWED_HOSTS = ['0.0.0.0', 'localhost', '127.0.0.1']
or
ALLOWED_HOSTS = ['*']
Add PostgreSQL to Database
Separate the Database config for development and server
if DEBUG:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': config('DATABASE_NAME'),
'USER': config('DATABASE_USER'),
'PASSWORD': config('DATABASE_PASSWORD'),
'HOST': config('DATABASE_HOST'),
'PORT': config('DATABASE_PORT'),
}
}
else:
import dj_database_url
# set server database configuration here
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
'NAME': 'fisdomapp',
'USER': 'name',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '',
}
}
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)
Now run the django server and validate everything works fine.
Every app static folder can be traced by django using staticfiles_storage. It’s similar to Template settings.
STATIC_URL = where the static files will server in local development
STATIC_ROOT = collect all static files for deployment (This need be Absolute path)
e.g,
STATIC_ROOT = os.path.join(BASE_DIR, “static”)
STATICFILES_DIRS = if app has Additional static files need to give in this it will be searched during findstatic and collectstatic commands.
create new folder in root folder location with the name ‘static’ and run below command
python manage.py collectstatic
This will collect all the static file for deployment and everything from admin to every app.
Add White noise settings in end of the settings to server static files in Heroku.
if not DEBUG:
MIDDLEWARE += ['whitenoise.middleware.WhiteNoiseMiddleware']
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
import django_heroku
django_heroku.settings(locals())
Add all the apps to Django core and test it locally . Next section is to adding configuration for heroku deployment.
2. Procfile
Create new Procfile in the root folder and add the above line . App name changes according to your django-admin app. My app name is core andwsgi file available there. Usually you have to give settings.py folder name.
web: gunicorn core.wsgi --log-file -
Heroku run the commands before server start app that are all mention inprocfile. We need to define server and worker(celery) here.
What ever the name your settings.py have e.g., sample/wsgi.py then web: gunicorn sample.wsgi –log-file -
3. requirements.py
We need to heroku to install our project dependency packages while building project. That we do by simple python run the below command in root of the project where (manage.py) is available
pip freeze > requirements.txt
This will generate the project dependency packages unfortunately with other packages depended with your depedency package. If you what are all added you can remove them else leave as it.
sample:
dj-database-url==0.5.0
Django==3.0.6
django-heroku==0.3.1
gunicorn==20.0.4
psycopg2==2.8.5
python-decouple==3.3
whitenoise==5.1.0
4. Heroku Login and Setup
Login to Heroku and create new app. Next go to root folder of location and run below command
Note: heroku cli need to install before running this
heroku login
After login you can use below commands
Create new git init folder if
git init
Add remote Heroku
heroku git:remote -a django-postgres-demo
5. Adding PostgreSQL Addon
Add PostgreSQL database to the current app
heroku addons:create heroku-postgresql:hobby-dev
###6. Migrate the change the Heroku PostgreSQL
heroku run python manage.py migrate
This will apply the local migrations to Heroku PostgreSQL
7. Add secret-key to Heroku
go to settings -> Revel config
Click Add -> new config variable SECRET_KEY
Finally push the changes to GitHub and Heroku
git push heroku master
If there is no issue. run below commanD
heroku ps:scale web=1
This command start the app after it’s deployed.
heroku logs --tail
Use above command to find out the error if still not clear use below technique
NOTE: If you face 500 error enable debug true in settings.py find the error then update the debug.
SAMPLE Code: https://github.com/armsarun/django-heroku
Reference Links:
Django Static File Handling = Python Anywhere