Setting Up Django with Heroku and PostgreSQL: A Complete Guide
Written on
Chapter 1: Introduction
Deploying a Django application on Heroku can be quite complex. In a previous post, I discussed how to set up a basic Django app on Heroku. However, a Django app truly shines when it is connected to a database, and Heroku does not support the default SQLite database that Django uses. Fortunately, Heroku offers PostgreSQL databases that are either free or inexpensive for developers working on personal projects. In this tutorial, I will guide you through the setup process.
Section 1.1: Local Development vs. Remote Deployment
To clarify, we are working with a Django application that runs locally on our machine. When executing the command:
python manage.py runserver
we can access the application at http://localhost:8000. In this local environment, the app uses db.sqlite3 as its database. However, when we deploy the application to Heroku at YourProjectName.herokuapp.com, it will need to connect to a PostgreSQL database instead.
By the conclusion of this guide, our goal is to have the application operate with SQLite during local development and switch to PostgreSQL in a production environment. Setting up PostgreSQL locally is possible, but that topic will be covered in a separate tutorial.
Section 1.2: Understanding DATABASE_URL
If you followed the instructions in my previous guide, Heroku automatically set up a PostgreSQL instance for your Django application without you even realizing it. In your project directory, utilize the Heroku CLI to check your configurations by running:
heroku config
If a PostgreSQL instance has been created and linked to your application, you should see something like this:
=== nameless-tundra-24362 Config Vars
DATABASE_URL: postgres://[DATABASE_INFO_HERE]
I've omitted the database information from the example above for security reasons, as this URL contains your database's location and access credentials. Anyone with this URL can access your database, so handle it with care. This URL is stored as an environment variable named DATABASE_URL, which can change, so it’s advisable not to hard-code it. Instead, we will refer to the variable DATABASE_URL throughout our application.
If the DATABASE_URL variable is not configured, it's likely that there is no PostgreSQL instance linked to your app, and you may need to create one manually.
Chapter 2: Configuring Your Django Application
To successfully implement PostgreSQL for remote use and SQLite for local development, several key adjustments are necessary in your application.
The first video titled "How to Deploy Django App on Heroku with PostgreSQL Database" provides a comprehensive overview of deploying your app. It will help you understand the deployment process better.
Section 2.1: Installing Required Packages
To proceed, we need to install the python-dotenv package, which will help manage environment variables. Navigate to your project’s root directory (where manage.py is located) and run:
pip install python-dotenv
This command will also install a related module called dj-database-url. After installation, update your requirements.txt file by executing:
pip freeze > requirements.txt
Section 2.2: Creating the .env File
We will create a file named .env to direct Django to utilize SQLite for local development. To generate the .env file and configure it for SQLite, execute:
echo 'DATABASE_URL=sqlite:///db.sqlite3' > .env
It is important to ensure that .env does not get pushed to Heroku since it points to SQLite, which is not supported there. To prevent this, add .env to your .gitignore file:
echo '.env' >> .gitignore
Section 2.3: Updating settings.py
Now that we have created the .env file, we need to modify Django's settings.py to utilize it. Here are the steps:
- At the beginning of the settings.py, import the necessary modules:
import dj_database_url
import dotenv
- Load environment variables from the .env file if it exists:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
dotenv_file = os.path.join(BASE_DIR, ".env")
if os.path.isfile(dotenv_file):
dotenv.load_dotenv(dotenv_file)
This ensures that when running on Heroku, the dotenv.load_dotenv(dotenv_file) call will not execute, allowing Heroku to find its own PostgreSQL database.
- Add WhiteNoise to the MIDDLEWARE list:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
...
]
Ensure that the Django security middleware is listed first.
- Modify the DATABASES setting:
Replace the current configuration:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
with the following:
DATABASES = {}
DATABASES['default'] = dj_database_url.config(conn_max_age=600)
This configuration clears the DATABASES variable and sets the default key using the dj_database_url module, which will dynamically select the appropriate database based on the environment.
- Configure STATICFILES_STORAGE for WhiteNoise:
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
It's best to place this in proximity to your STATIC_URL and STATIC_ROOT settings.
- Addressing sslmode Issues:
If you run into SSL-related errors while using the dj_database_url module locally, you can add a workaround at the end of your settings.py file:
django_heroku.settings(locals())
options = DATABASES['default'].get('OPTIONS', {})
options.pop('sslmode', None)
Section 2.4: Testing Your Setup
To verify that everything is working correctly, test your application locally:
python manage.py runserver
You should be able to connect to the local SQLite database and run migrations:
python manage.py migrate
Create a superuser for the local database admin with:
python manage.py createsuperuser
Check the admin interface by visiting http://localhost:8000/admin/ and logging in with your superuser credentials.
Section 2.5: Deploying to Heroku
Next, let’s push our local changes to Heroku:
git add .
git commit -am "Implement database connection"
git push heroku master
Monitor the output to ensure that everything builds successfully. Once deployed, verify the URL to confirm it is working:
Section 2.6: Running Migrations on Heroku
To connect to the Heroku PostgreSQL instance and run migrations, access the Heroku shell with:
heroku run bash
Then, execute:
python manage.py migrate
If you need to create a superuser in the Heroku PostgreSQL database, run:
python manage.py createsuperuser
You can then navigate to your Heroku app's admin panel to ensure everything is functional.
Congratulations on getting your Django application up and running on Heroku with a PostgreSQL database! You are now free to expand your app by adding views, URLs, models, and more.
If you have any questions or need further assistance, feel free to leave your comments below.
The second video titled "Heroku Postgres Connection | Django (3.0) Crash Course Tutorials (pt 24)" delves deeper into connecting Django with Heroku Postgres, offering valuable insights and tips.