Skip to content

Commit c99a168

Browse files
authored
Don't provision a Postgres database by default (#203)
* The app no longer provisions a Postgres addon by default (since the Postgres adapter dependency in `requirements.txt` is commented out, which is what the Python buildpack uses to determine whether to auto-provision), so that it's possible to try the main part of the guide without incurring any additional charges beyond the eco dyno plan. * The Postgres DB addon has been removed from `app.json` too, which prevents it from being auto-provisioned for Review Apps too. * Help comments has been added to the `db` view function, to try and help prevent confusion due to errors on Heroku from the DB not being auto-provisioned. * The Postgres adapter has been switched from `psycopg2` to `psycopg`, which counter-intuitively is newer (`psycopg` is the v3 implementation of the adapter). The binary version of the package is now also used when not in production, to speed up local installation and reduce the chance of running into library/header issues. * The new Django DB connection health check feature has been enabled. * The unnecessary `HerokuDiscoverRunner` custom test runner and database`TEST` options have been removed. * An example `release` process entry has been added (commented out) to `Procfile`, which runs the Django DB migrations using the Heroku Release Phase feature. GUS-W-13152716.
1 parent 8bac412 commit c99a168

File tree

5 files changed

+53
-41
lines changed

5 files changed

+53
-41
lines changed

Procfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
web: gunicorn gettingstarted.wsgi
2+
3+
# Uncomment this `release` process if you are using a database, so that Django's model
4+
# migrations are run as part of app deployment, using Heroku's Release Phase feature:
5+
# https://docs.djangoproject.com/en/4.2/topics/migrations/
6+
# https://devcenter.heroku.com/articles/release-phase
7+
#release: ./manage.py migrate --no-input

app.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"image": "heroku/python",
55
"repository": "https://github.com/heroku/python-getting-started",
66
"keywords": ["python", "django"],
7-
"addons": ["heroku-postgresql"],
87
"env": {
98
"DJANGO_SECRET_KEY": {
109
"description": "The secret key for the Django application.",

gettingstarted/settings.py

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@
1515
from pathlib import Path
1616

1717
import dj_database_url
18-
from django.test.runner import DiscoverRunner
1918

2019
# Build paths inside the project like this: BASE_DIR / 'subdir'.
2120
BASE_DIR = Path(__file__).resolve().parent.parent
2221

2322

24-
IS_HEROKU = "DYNO" in os.environ
25-
2623
# Before using your Heroku app in production, make sure to review Django's deployment checklist:
2724
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
2825

@@ -40,15 +37,20 @@
4037
default=secrets.token_urlsafe(nbytes=64),
4138
)
4239

40+
# The `DYNO` env var is set on Heroku CI, but it's not a real Heroku app, so we have to
41+
# also explicitly exclude CI:
42+
# https://devcenter.heroku.com/articles/heroku-ci#immutable-environment-variables
43+
IS_HEROKU_APP = "DYNO" in os.environ and not "CI" in os.environ
44+
4345
# SECURITY WARNING: don't run with debug turned on in production!
44-
if not IS_HEROKU:
46+
if not IS_HEROKU_APP:
4547
DEBUG = True
4648

4749
# On Heroku, it's safe to use a wildcard for `ALLOWED_HOSTS``, since the Heroku router performs
4850
# validation of the Host header in the incoming HTTP request. On other platforms you may need
4951
# to list the expected hostnames explicitly to prevent HTTP Host header attacks. See:
5052
# https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-ALLOWED_HOSTS
51-
if IS_HEROKU:
53+
if IS_HEROKU_APP:
5254
ALLOWED_HOSTS = ["*"]
5355
else:
5456
ALLOWED_HOSTS = []
@@ -109,25 +111,28 @@
109111
# Database
110112
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
111113

112-
MAX_CONN_AGE = 600
113-
114-
DATABASES = {
115-
"default": {
116-
"ENGINE": "django.db.backends.sqlite3",
117-
"NAME": BASE_DIR / "db.sqlite3",
114+
if IS_HEROKU_APP:
115+
# In production on Heroku the database configuration is derived from the `DATABASE_URL`
116+
# environment variable by the dj-database-url package. `DATABASE_URL` will be set
117+
# automatically by Heroku when a database addon is attached to your Heroku app. See:
118+
# https://devcenter.heroku.com/articles/provisioning-heroku-postgres
119+
# https://github.com/jazzband/dj-database-url
120+
DATABASES = {
121+
"default": dj_database_url.config(
122+
conn_max_age=600,
123+
conn_health_checks=True,
124+
ssl_require=True,
125+
),
126+
}
127+
else:
128+
# When running locally in development or in CI, a sqlite database file will be used instead
129+
# to simplify initial setup. Longer term it's recommended to use Postgres locally too.
130+
DATABASES = {
131+
"default": {
132+
"ENGINE": "django.db.backends.sqlite3",
133+
"NAME": BASE_DIR / "db.sqlite3",
134+
}
118135
}
119-
}
120-
121-
if "DATABASE_URL" in os.environ:
122-
# Configure Django for DATABASE_URL environment variable.
123-
DATABASES["default"] = dj_database_url.config(
124-
conn_max_age=MAX_CONN_AGE,
125-
ssl_require=True,
126-
)
127-
128-
# Enable test database if found in CI environment.
129-
if "CI" in os.environ:
130-
DATABASES["default"]["TEST"] = DATABASES["default"]
131136

132137

133138
# Password validation
@@ -180,21 +185,6 @@
180185
WHITENOISE_KEEP_ONLY_HASHED_FILES = True
181186

182187

183-
# Test Runner Config
184-
class HerokuDiscoverRunner(DiscoverRunner):
185-
"""Test Runner for Heroku CI, which provides a database for you.
186-
This requires you to set the TEST database (done for you by settings().)"""
187-
188-
def setup_databases(self, **kwargs):
189-
self.keepdb = True
190-
return super(HerokuDiscoverRunner, self).setup_databases(**kwargs)
191-
192-
193-
# Use HerokuDiscoverRunner on Heroku CI
194-
if "CI" in os.environ:
195-
TEST_RUNNER = "gettingstarted.settings.HerokuDiscoverRunner"
196-
197-
198188
# Default primary key field type
199189
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
200190

hello/views.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ def index(request):
1010

1111

1212
def db(request):
13+
# If you encounter errors visiting the `/db/` page on the example app, check that:
14+
#
15+
# When running the app on Heroku:
16+
# 1. You have added the Postgres database to your app.
17+
# 2. You have uncommented the `psycopg` dependency in `requirements.txt`, and the `release`
18+
# process entry in `Procfile`, git committed your changes and re-deployed the app.
19+
#
20+
# When running the app locally:
21+
# 1. You have run `./manage.py migrate` to create the `hello_greeting` database table.
22+
1323
greeting = Greeting()
1424
greeting.save()
1525

requirements.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
django>=4.0,<5.0
1+
django>=4.2,<5.0
22
gunicorn>=20.0,<21.0
33
dj-database-url>=2.0,<3.0
44
whitenoise[brotli]>=6.0,<7.0
5-
psycopg2>=2.0,<3.0
5+
6+
# Uncomment these lines to use a Postgres database. Both are needed, since in production
7+
# (which uses Linux) we want to install from source, so that security updates from the
8+
# underlying Heroku stack image are picked up automatically, thanks to dynamic linking.
9+
# On other platforms/in development, the precompiled binary package is used instead, to
10+
# speed up installation and avoid errors from missing libraries/headers.
11+
#psycopg; sys_platform == "linux"
12+
#psycopg[binary]; sys_platform != "linux"

0 commit comments

Comments
 (0)