From bd14b509c61906a38453e7904d039121d8393d06 Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Wed, 6 Jul 2016 18:22:50 +0800 Subject: [PATCH 001/143] Update Python version in runtime.txt --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 0239feabb..fdf79660d 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-2.7.11 +python-2.7.12 From 1591d6d4e298cd2fb019689fd44c6bc12402982b Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Wed, 6 Jul 2016 18:30:13 +0800 Subject: [PATCH 002/143] Update requirements.txt --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 5ced65136..4616522a6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -dj-database-url==0.4.0 -Django==1.9.2 -gunicorn==19.4.5 +dj-database-url==0.4.1 +Django==1.9.7 +gunicorn==19.6.0 psycopg2==2.6.1 whitenoise==2.0.6 From 4ae7a8606aebddf0a2eee749df91e59c7b75f0d4 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sat, 17 Dec 2016 19:00:22 -0500 Subject: [PATCH 003/143] Update runtime.txt --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index fdf79660d..4b38fc9ad 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-2.7.12 +python-2.7.13 From 2b36b05ce15d1dfc88e0b52580074c4a5036f310 Mon Sep 17 00:00:00 2001 From: odazai Date: Sat, 7 Jan 2017 17:49:11 +0800 Subject: [PATCH 004/143] Update requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 4616522a6..ad188d554 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ Django==1.9.7 gunicorn==19.6.0 psycopg2==2.6.1 whitenoise==2.0.6 +requests==2.9.1 From 2f24fe3f04147ac8f7aa1627edec5286362d30fe Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 29 Mar 2017 11:29:53 -0400 Subject: [PATCH 005/143] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4616522a6..92a9f6b53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ dj-database-url==0.4.1 Django==1.9.7 gunicorn==19.6.0 -psycopg2==2.6.1 +psycopg2==2.6.2 whitenoise==2.0.6 From 93eb173290be84690642ddbcbcfd235704af13db Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 10 Apr 2017 10:17:22 -0400 Subject: [PATCH 006/143] Revert "Merge pull request #27 from odazai/patch-2" This reverts commit 959ec1c071dc55d29cf773cfce934dd36c808ac6, reversing changes made to 2f24fe3f04147ac8f7aa1627edec5286362d30fe. --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7cbe27cd4..92a9f6b53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,3 @@ Django==1.9.7 gunicorn==19.6.0 psycopg2==2.6.2 whitenoise==2.0.6 -requests==2.9.1 From bd90123510bc5894ca7541d6577fcc23e9bc150d Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 13 Apr 2017 11:02:51 -0400 Subject: [PATCH 007/143] Update runtime.txt --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 4b38fc9ad..3a799ff62 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-2.7.13 +python-3.6.0 From 11cc75d36c771752071c40158c3fcaca270ea0ef Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 25 May 2017 12:33:01 -0400 Subject: [PATCH 008/143] Update runtime.txt --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 3a799ff62..c91e43be5 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.6.0 +python-3.6.1 From 19a831771a21313a9ab78000f85abe4868944d91 Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 4 Jul 2017 10:14:02 -0400 Subject: [PATCH 009/143] update django version for support until at least 2020 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 92a9f6b53..2db16fb1c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ dj-database-url==0.4.1 -Django==1.9.7 +Django==1.11 gunicorn==19.6.0 psycopg2==2.6.2 whitenoise==2.0.6 From 5103137b0c0db70ba791cc6e00069187707701ef Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 17 Jul 2017 12:02:20 -0400 Subject: [PATCH 010/143] update to python-3.6.2 --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index c91e43be5..cfa5aa5ca 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.6.1 +python-3.6.2 From 4223bbf4de5a89a1bce678784b2aa2497e177de0 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 26 Jul 2017 17:47:58 -0400 Subject: [PATCH 011/143] tests Signed-off-by: Kenneth Reitz --- .gitignore | 2 ++ app.json | 9 ++++++++- hello/tests.py | 19 +++++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f95d164a6..97d5f7d76 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ venv staticfiles .env db.sqlite3 + +/Pipfile diff --git a/app.json b/app.json index 00281c3c7..94a50dd4f 100644 --- a/app.json +++ b/app.json @@ -4,5 +4,12 @@ "image": "heroku/python", "repository": "https://github.com/heroku/python-getting-started", "keywords": ["python", "django" ], - "addons": [ "heroku-postgresql" ] + "addons": [ "heroku-postgresql" ], + "environments": { + "test": { + "scripts": { + "test": "python manage.py test" + } + } + } } diff --git a/hello/tests.py b/hello/tests.py index 7ce503c2d..1d69113fe 100644 --- a/hello/tests.py +++ b/hello/tests.py @@ -1,3 +1,18 @@ -from django.test import TestCase +from django.contrib.auth.models import AnonymousUser, User +from django.test import TestCase, RequestFactory -# Create your tests here. +from .views import index + +class SimpleTest(TestCase): + def setUp(self): + # Every test needs access to the request factory. + self.factory = RequestFactory() + + def test_details(self): + # Create an instance of a GET request. + request = self.factory.get('/') + request.user = AnonymousUser() + + # Test my_view() as if it were deployed at /customer/details + response = index(request) + self.assertEqual(response.status_code, 200) \ No newline at end of file From 24f614d10ecde4996b4ead256c04309c8881b1e8 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 26 Jul 2017 17:54:48 -0400 Subject: [PATCH 012/143] heroku test runner --- gettingstarted/heroku_test_runner.py | 55 ++++++++++++++++++++++++++++ gettingstarted/settings.py | 2 + 2 files changed, 57 insertions(+) create mode 100644 gettingstarted/heroku_test_runner.py diff --git a/gettingstarted/heroku_test_runner.py b/gettingstarted/heroku_test_runner.py new file mode 100644 index 000000000..7a8a1447a --- /dev/null +++ b/gettingstarted/heroku_test_runner.py @@ -0,0 +1,55 @@ +import os + +from django.test.runner import DiscoverRunner + +""" +WARNING: WHEN USED INCORRECTLY THIS TEST RUNNER WILL DROP ALL TABLES IN YOUR PRODUCTION +DATABASE!!! + +Heroku does not give users createdb/dropdb permissions, therefore Heroku CI cannot run tests for django. +In order to fix this, use this test runner instead which attempts to minimally override the +default test runner by a) forcing keepdb=True to stop database create/drop, and b) by dropping all +tables after a test run and resetting the database to its initial blank state. + +Usage: + +1. In your django test settings file add the following two lines to ensure that the test +database name is the same as the Heroku provided database name. + +DATABASES['default'] = env.db('DATABASE_URL') # or whatever you use to load the Heroku database settings +DATABASES['default']['TEST'] = {'NAME': DATABASES['default']['NAME']} + +2. Set the testrunner to this file +TEST_RUNNER = 'your_modules.HerokuDiscoverRunner' + +3. Set an environment variable on heroku CI of IS_HEROKU_TEST=1 to enable this runner, otherwise +the runner will exit as a safety measure. +""" + +class HerokuDiscoverRunner(DiscoverRunner): + def setup_databases(self, **kwargs): + if not os.environ.get('IS_HEROKU_TEST'): + raise ValueError( + "The IS_HEROKU_TEST env variable must be set to enable this. WARNING: " + "This test runner will wipe all tables in the database it targets!") + self.keepdb = True + return super(HerokuDiscoverRunner, self).setup_databases(**kwargs) + + def _wipe_tables(self, connection): + with connection.cursor() as cursor: + cursor.execute( + """ + DROP SCHEMA public CASCADE; + CREATE SCHEMA public; + GRANT ALL ON SCHEMA public TO postgres; + GRANT ALL ON SCHEMA public TO public; + COMMENT ON SCHEMA public IS 'standard public schema'; + """ + ) + + def teardown_databases(self, old_config, **kwargs): + self.keepdb = True + for connection, old_name, destroy in old_config: + if destroy: + self._wipe_tables(connection) + super(HerokuDiscoverRunner, self).teardown_databases(old_config, **kwargs) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 15a865023..f17d4eaf4 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -27,6 +27,8 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +TEST_RUNNER = 'gettingstarted.heroku_test_runner.HerokuDiscoverRunner' + # Application definition From 91c05703aff13abff5aaa2f6ffe43afb953658f8 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 26 Jul 2017 17:57:44 -0400 Subject: [PATCH 013/143] update test database name --- gettingstarted/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index f17d4eaf4..85eb7f9e7 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -116,6 +116,7 @@ # Update database configuration with $DATABASE_URL. db_from_env = dj_database_url.config(conn_max_age=500) DATABASES['default'].update(db_from_env) +DATABASES['default']['TEST'] = {'NAME': DATABASES['default']['NAME']} # Honor the 'X-Forwarded-Proto' header for request.is_secure() SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') From bf25cf6acd324a8bffc4d2f5dc472840ef6ab6e7 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 26 Jul 2017 18:00:59 -0400 Subject: [PATCH 014/143] collectstatic --noinput for tests --- app.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app.json b/app.json index 94a50dd4f..8cba47e35 100644 --- a/app.json +++ b/app.json @@ -8,6 +8,7 @@ "environments": { "test": { "scripts": { + "test-setup": "python manage.py collectstatic --noinput", "test": "python manage.py test" } } From fcb7592b8e1fc244cc507276d32f9f5e53a1f383 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 27 Jul 2017 16:02:59 -0400 Subject: [PATCH 015/143] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30cc47c48..5cdff5e3c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# python-getting-started +# Python: Getting Started A barebones Python app, which can easily be deployed to Heroku. From 5a4603e28872f3a8e7011a15c86fd59b8bbbcc66 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 27 Jul 2017 16:03:12 -0400 Subject: [PATCH 016/143] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5cdff5e3c..a5f508fea 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Python: Getting Started -A barebones Python app, which can easily be deployed to Heroku. +A barebones Django app, which can easily be deployed to Heroku. This application supports the [Getting Started with Python on Heroku](https://devcenter.heroku.com/articles/getting-started-with-python) article - check it out. From 39546f1ea767f4becb6946f8734e6145443631bf Mon Sep 17 00:00:00 2001 From: David Evans Date: Fri, 28 Jul 2017 15:46:50 +0100 Subject: [PATCH 017/143] Upgrade WhiteNoise and switch to Django middleware --- gettingstarted/settings.py | 5 ++++- gettingstarted/wsgi.py | 2 -- requirements.txt | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 85eb7f9e7..ab15fea8b 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -43,6 +43,9 @@ ) MIDDLEWARE_CLASSES = ( + # Simplified static file serving. + # https://warehouse.python.org/project/whitenoise/ + 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -137,5 +140,5 @@ # Simplified static file serving. # https://warehouse.python.org/project/whitenoise/ -STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage' +STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' diff --git a/gettingstarted/wsgi.py b/gettingstarted/wsgi.py index 620b37498..feb0af46f 100644 --- a/gettingstarted/wsgi.py +++ b/gettingstarted/wsgi.py @@ -11,7 +11,5 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gettingstarted.settings") from django.core.wsgi import get_wsgi_application -from whitenoise.django import DjangoWhiteNoise application = get_wsgi_application() -application = DjangoWhiteNoise(application) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2db16fb1c..5edeb5b89 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ dj-database-url==0.4.1 Django==1.11 gunicorn==19.6.0 psycopg2==2.6.2 -whitenoise==2.0.6 +whitenoise==3.3.0 From ea03f9148dd9f63a510495931cc803760c7a60f4 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 31 Aug 2017 11:50:43 -0400 Subject: [PATCH 018/143] switch to pipfile Signed-off-by: Kenneth Reitz --- Pipfile | 13 +++++++++++++ Pipfile.lock | 37 +++++++++++++++++++++++++++++++++++++ README.md | 2 +- requirements.txt | 5 ----- runtime.txt | 1 - 5 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 Pipfile create mode 100644 Pipfile.lock delete mode 100644 requirements.txt delete mode 100644 runtime.txt diff --git a/Pipfile b/Pipfile new file mode 100644 index 000000000..fa4e79d47 --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true + +[packages] +dj-database-url = "*" +django = "*" +gunicorn = "*" +psycopg2 = "*" +whitenoise = "*" + +[requires] +python_version = "3.6" \ No newline at end of file diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 000000000..3958b6b66 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,37 @@ +{ + "_meta": { + "hash": { + "sha256": "c48e4947852b09e706177c0432ea536fe7d0f5f293afef2d4e592035f736121f" + }, + "requires": { + "python_version": "3.6" + }, + "sources": [ + { + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "dj-database-url": { + "version": "==0.4.2" + }, + "django": { + "version": "==1.11.4" + }, + "gunicorn": { + "version": "==19.7.1" + }, + "psycopg2": { + "version": "==2.7.3.1" + }, + "pytz": { + "version": "==2017.2" + }, + "whitenoise": { + "version": "==3.3.0" + } + }, + "develop": {} +} diff --git a/README.md b/README.md index a5f508fea..26bc7731a 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Make sure you have Python [installed properly](http://install.python-guide.org). $ git clone git@github.com:heroku/python-getting-started.git $ cd python-getting-started -$ pip install -r requirements.txt +$ pipenv install $ createdb python_getting_started diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 5edeb5b89..000000000 --- a/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -dj-database-url==0.4.1 -Django==1.11 -gunicorn==19.6.0 -psycopg2==2.6.2 -whitenoise==3.3.0 diff --git a/runtime.txt b/runtime.txt deleted file mode 100644 index cfa5aa5ca..000000000 --- a/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.6.2 From ee4ed11262b3b4128c6b349557b878c25c21f431 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 31 Aug 2017 11:50:51 -0400 Subject: [PATCH 019/143] remove pipfile from gitignore Signed-off-by: Kenneth Reitz --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 97d5f7d76..f95d164a6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,3 @@ venv staticfiles .env db.sqlite3 - -/Pipfile From 997f2e2f3ff5656731f52e8dbdb102544bcef281 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 31 Aug 2017 13:16:43 -0400 Subject: [PATCH 020/143] empty commit From 3fca2c9f511555ba9a449a31bc47ba3193fca317 Mon Sep 17 00:00:00 2001 From: Jordan Danford Date: Fri, 1 Sep 2017 09:45:05 -0700 Subject: [PATCH 021/143] Update link to Heroku CLI --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26bc7731a..477cb9169 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This application supports the [Getting Started with Python on Heroku](https://de ## Running Locally -Make sure you have Python [installed properly](http://install.python-guide.org). Also, install the [Heroku Toolbelt](https://toolbelt.heroku.com/) and [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). +Make sure you have Python [installed properly](http://install.python-guide.org). Also, install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) and [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). ```sh $ git clone git@github.com:heroku/python-getting-started.git From c0b2b157b585283428f6115b5f431cf2ac61aa12 Mon Sep 17 00:00:00 2001 From: Jordan Danford Date: Fri, 1 Sep 2017 14:50:29 -0700 Subject: [PATCH 022/143] Use SVG version of "Deploy" button --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26bc7731a..6f0b6f4d9 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ $ heroku open ``` or -[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) ## Documentation From affbf35867657876291dca73264a8be3c23069cd Mon Sep 17 00:00:00 2001 From: Otto Jongerius Date: Wed, 13 Sep 2017 10:22:00 +1200 Subject: [PATCH 023/143] No longer using requirements.txt but Pipfile. Updates template to reflect that requirements.txt has been superseded by Pipfile. --- hello/templates/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hello/templates/index.html b/hello/templates/index.html index 3c7236392..8af29028b 100644 --- a/hello/templates/index.html +++ b/hello/templates/index.html @@ -25,7 +25,7 @@

How this sample app work
  • This app was deployed to Heroku, either using Git or by using Heroku Button on the repository.
  • -
  • When Heroku received the source code, it fetched all the dependencies in the requirements.txt file, creating a deployable slug.
  • +
  • When Heroku received the source code, it fetched all the dependencies in the Pipfile, creating a deployable slug.
  • The platform then spins up a dyno, a lightweight container that provides an isolated environment in which the slug can be mounted and executed.
  • You can scale your app, manage it, and deploy over 150 add-on services, from the Dashboard or CLI.
From 7b995b5b91d41f16b32b140f02d48262833371b8 Mon Sep 17 00:00:00 2001 From: Kyle Stone Date: Fri, 3 Nov 2017 21:10:50 -0400 Subject: [PATCH 024/143] Demo Origato Mr. Roboto. --- Pipfile | 10 +++- Pipfile.lock | 119 ++++++++++++++++++++++++++++++++++++++++++++++-- hello/views.py | 7 ++- hello/views.py~ | 21 +++++++++ 4 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 hello/views.py~ diff --git a/Pipfile b/Pipfile index fa4e79d47..dee8c1ff6 100644 --- a/Pipfile +++ b/Pipfile @@ -1,13 +1,19 @@ [[source]] + url = "https://pypi.python.org/simple" verify_ssl = true + [packages] + dj-database-url = "*" django = "*" gunicorn = "*" -psycopg2 = "*" +"psycopg2" = "*" whitenoise = "*" +requests = "*" + [requires] -python_version = "3.6" \ No newline at end of file + +python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 3958b6b66..2b1a6d6b6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,8 +1,22 @@ { "_meta": { "hash": { - "sha256": "c48e4947852b09e706177c0432ea536fe7d0f5f293afef2d4e592035f736121f" + "sha256": "5f92a81f5aa11881493a2e0b0a2b80f5230dd044a744462cda905e9e07342442" }, + "host-environment-markers": { + "implementation_name": "cpython", + "implementation_version": "3.6.3", + "os_name": "posix", + "platform_machine": "x86_64", + "platform_python_implementation": "CPython", + "platform_release": "16.7.0", + "platform_system": "Darwin", + "platform_version": "Darwin Kernel Version 16.7.0: Wed Oct 4 00:17:00 PDT 2017; root:xnu-3789.71.6~1/RELEASE_X86_64", + "python_full_version": "3.6.3", + "python_version": "3.6", + "sys_platform": "darwin" + }, + "pipfile-spec": 6, "requires": { "python_version": "3.6" }, @@ -14,23 +28,118 @@ ] }, "default": { + "certifi": { + "hashes": [ + "sha256:54a07c09c586b0e4c619f02a5e94e36619da8e2b053e20f594348c0611803704", + "sha256:40523d2efb60523e113b44602298f0960e900388cf3bb6043f645cf57ea9e3f5" + ], + "version": "==2017.7.27.1" + }, + "chardet": { + "hashes": [ + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" + ], + "version": "==3.0.4" + }, "dj-database-url": { + "hashes": [ + "sha256:e16d94c382ea0564c48038fa7fe8d9c890ef1ab1a8ec4cb48e732c124b9482fd", + "sha256:a6832d8445ee9d788c5baa48aef8130bf61fdc442f7d9a548424d25cd85c9f08" + ], "version": "==0.4.2" }, "django": { - "version": "==1.11.4" + "hashes": [ + "sha256:75ce405d60f092f6adf904058d023eeea0e6d380f8d9c36134bac73da736023d", + "sha256:8918e392530d8fc6965a56af6504229e7924c27265893f3949aa0529cd1d4b99" + ], + "version": "==1.11.7" }, "gunicorn": { + "hashes": [ + "sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6", + "sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622" + ], "version": "==19.7.1" }, + "idna": { + "hashes": [ + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" + ], + "version": "==2.6" + }, "psycopg2": { - "version": "==2.7.3.1" + "hashes": [ + "sha256:594aa9a095de16614f703d759e10c018bdffeafce2921b8e80a0e8a0ebbc12e5", + "sha256:1cf5d84290c771eeecb734abe2c6c3120e9837eb12f99474141a862b9061ac51", + "sha256:0344b181e1aea37a58c218ccb0f0f771295de9aa25a625ed076e6996c6530f9e", + "sha256:25250867a4cd1510fb755ef9cb38da3065def999d8e92c44e49a39b9b76bc893", + "sha256:317612d5d0ca4a9f7e42afb2add69b10be360784d21ce4ecfbca19f1f5eadf43", + "sha256:9d6266348b15b4a48623bf4d3e50445d8e581da413644f365805b321703d0fac", + "sha256:ddca39cc55877653b5fcf59976d073e3d58c7c406ef54ae8e61ddf8782867182", + "sha256:988d2ec7560d42ef0ac34b3b97aad14c4f068792f00e1524fa1d3749fe4e4b64", + "sha256:7a9c6c62e6e05df5406e9b5235c31c376a22620ef26715a663cee57083b3c2ea", + "sha256:7a75565181e75ba0b9fb174b58172bf6ea9b4331631cfe7bafff03f3641f5d73", + "sha256:94e4128ba1ea56f02522fffac65520091a9de3f5c00da31539e085e13db4771b", + "sha256:92179bd68c2efe72924a99b6745a9172471931fc296f9bfdf9645b75eebd6344", + "sha256:b9358e203168fef7bfe9f430afaed3a2a624717a1d19c7afa7dfcbd76e3cd95c", + "sha256:009e0bc09a57dbef4b601cb8b46a2abad51f5274c8be4bba276ff2884cd4cc53", + "sha256:d3ac07240e2304181ffdb13c099840b5eb555efc7be9344503c0c03aa681de79", + "sha256:40fa5630cd7d237cd93c4d4b64b9e5ed9273d1cfce55241c7f9066f5db70629d", + "sha256:6c2f1a76a9ebd9ecf7825b9e20860139ca502c2bf1beabf6accf6c9e66a7e0c3", + "sha256:37f54452c7787dbdc0a634ca9773362b91709917f0b365ed14b831f03cbd34ba", + "sha256:8f5942a4daf1ffac42109dc4a72f786af4baa4fa702ede1d7c57b4b696c2e7d6", + "sha256:bf708455cd1e9fa96c05126e89a0c59b200d086c7df7bbafc7d9be769e4149a3", + "sha256:82c40ea3ac1555e0462803380609fbe8b26f52620f3d4f8eb480cfd8ceed8a14", + "sha256:207ba4f9125a0a4200691e82d5eee7ea1485708eabe99a07fc7f08696fae62f4", + "sha256:0cd4c848f0e9d805d531e44973c8f48962e20eb7fc0edac3db4f9dbf9ed5ab82", + "sha256:57baf63aeb2965ca4b52613ce78e968b6d2bde700c97f6a7e8c6c236b51ab83e", + "sha256:2954557393cfc9a5c11a5199c7a78cd9c0c793a047552d27b1636da50d013916", + "sha256:7c31dade89634807196a6b20ced831fbd5bec8a21c4e458ea950c9102c3aa96f", + "sha256:1286dd16d0e46d59fa54582725986704a7a3f3d9aca6c5902a7eceb10c60cb7e", + "sha256:697ff63bc5451e0b0db48ad205151123d25683b3754198be7ab5fcb44334e519", + "sha256:fc993c9331d91766d54757bbc70231e29d5ceb2d1ac08b1570feaa0c38ab9582", + "sha256:9d64fed2681552ed642e9c0cc831a9e95ab91de72b47d0cb68b5bf506ba88647", + "sha256:5c3213be557d0468f9df8fe2487eaf2990d9799202c5ff5cb8d394d09fad9b2a" + ], + "version": "==2.7.3.2" }, "pytz": { - "version": "==2017.2" + "hashes": [ + "sha256:80af0f3008046b9975242012a985f04c5df1f01eed4ec1633d56cc47a75a6a48", + "sha256:feb2365914948b8620347784b6b6da356f31c9d03560259070b2f30cff3d469d", + "sha256:59707844a9825589878236ff2f4e0dc9958511b7ffaae94dc615da07d4a68d33", + "sha256:d0ef5ef55ed3d37854320d4926b04a4cb42a2e88f71da9ddfdacfde8e364f027", + "sha256:c41c62827ce9cafacd6f2f7018e4f83a6f1986e87bfd000b8cfbd4ab5da95f1a", + "sha256:8cc90340159b5d7ced6f2ba77694d946fc975b09f1a51d93f3ce3bb399396f94", + "sha256:dd2e4ca6ce3785c8dd342d1853dd9052b19290d5bf66060846e5dc6b8d6667f7", + "sha256:699d18a2a56f19ee5698ab1123bbcc1d269d061996aeb1eda6d89248d3542b82", + "sha256:fae4cffc040921b8a2d60c6cf0b5d662c1190fe54d718271db4eb17d44a185b7" + ], + "version": "==2017.3" + }, + "requests": { + "hashes": [ + "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", + "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + ], + "version": "==2.18.4" + }, + "urllib3": { + "hashes": [ + "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", + "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + ], + "version": "==1.22" }, "whitenoise": { - "version": "==3.3.0" + "hashes": [ + "sha256:15f43b2e701821b95c9016cf469d29e2a546cb1c7dead584ba82c36f843995cf", + "sha256:9d81515f2b5b27051910996e1e860b1332e354d9e7bcf30c98f21dcb6713e0dd" + ], + "version": "==3.3.1" } }, "develop": {} diff --git a/hello/views.py b/hello/views.py index 8558d8451..3e882edb9 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,3 +1,4 @@ +import requests from django.shortcuts import render from django.http import HttpResponse @@ -5,8 +6,10 @@ # Create your views here. def index(request): - # return HttpResponse('Hello from Python!') - return render(request, 'index.html') + r = requests.get('http://httpbin.org/status/418') + print(r.text) + return HttpResponse('
' + r.text + '
Hello from Python!') + #return render(request, 'index.html') def db(request): diff --git a/hello/views.py~ b/hello/views.py~ new file mode 100644 index 000000000..354e993cd --- /dev/null +++ b/hello/views.py~ @@ -0,0 +1,21 @@ +import requests +from django.shortcuts import render +from django.http import HttpResponse + +from .models import Greeting + +# Create your views here. +def index(request): + # return HttpResponse('Hello from Python!') + return render(request, 'index.html') + + +def db(request): + + greeting = Greeting() + greeting.save() + + greetings = Greeting.objects.all() + + return render(request, 'db.html', {'greetings': greetings}) + From 90353e0b89743f6f13cc67c74e5873f1ce8d277b Mon Sep 17 00:00:00 2001 From: Kyle Stone Date: Mon, 6 Nov 2017 13:05:51 -0500 Subject: [PATCH 025/143] Updoot. --- .env | 2 +- .env~ | 1 + hello/views.py | 4 +++- hello/views.py~ | 8 ++++++-- 4 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .env~ diff --git a/.env b/.env index 06f57c520..2c8ba8ad5 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -TIMES=2 +TIMES=5 diff --git a/.env~ b/.env~ new file mode 100644 index 000000000..06f57c520 --- /dev/null +++ b/.env~ @@ -0,0 +1 @@ +TIMES=2 diff --git a/hello/views.py b/hello/views.py index 3e882edb9..e1ec9f9ca 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,3 +1,4 @@ +import os import requests from django.shortcuts import render from django.http import HttpResponse @@ -8,7 +9,8 @@ def index(request): r = requests.get('http://httpbin.org/status/418') print(r.text) - return HttpResponse('
' + r.text + '
Hello from Python!') + times= int(os.environ.get('TIMES', 3)) + return HttpResponse(('
' + r.text + '
Hello from Python!') * times) #return render(request, 'index.html') diff --git a/hello/views.py~ b/hello/views.py~ index 354e993cd..4d9026cc3 100644 --- a/hello/views.py~ +++ b/hello/views.py~ @@ -1,3 +1,4 @@ +import os import requests from django.shortcuts import render from django.http import HttpResponse @@ -6,8 +7,11 @@ from .models import Greeting # Create your views here. def index(request): - # return HttpResponse('Hello from Python!') - return render(request, 'index.html') + r = requests.get('http://httpbin.org/status/418') + print(r.text) + times= int(os.environ.get('TIMES', 3)) + return HttpResponse('
' + r.text + '
Hello from Python!' * times) + #return render(request, 'index.html') def db(request): From 1fa6af53343ac57a41f1870994310768a478f6b7 Mon Sep 17 00:00:00 2001 From: Kyle Stone Date: Mon, 13 Nov 2017 16:06:15 -0500 Subject: [PATCH 026/143] Revert "Updoot." This reverts commit 90353e0b89743f6f13cc67c74e5873f1ce8d277b. --- .env | 2 +- .env~ | 1 - hello/views.py | 4 +--- hello/views.py~ | 8 ++------ 4 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 .env~ diff --git a/.env b/.env index 2c8ba8ad5..06f57c520 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -TIMES=5 +TIMES=2 diff --git a/.env~ b/.env~ deleted file mode 100644 index 06f57c520..000000000 --- a/.env~ +++ /dev/null @@ -1 +0,0 @@ -TIMES=2 diff --git a/hello/views.py b/hello/views.py index e1ec9f9ca..3e882edb9 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,4 +1,3 @@ -import os import requests from django.shortcuts import render from django.http import HttpResponse @@ -9,8 +8,7 @@ def index(request): r = requests.get('http://httpbin.org/status/418') print(r.text) - times= int(os.environ.get('TIMES', 3)) - return HttpResponse(('
' + r.text + '
Hello from Python!') * times) + return HttpResponse('
' + r.text + '
Hello from Python!') #return render(request, 'index.html') diff --git a/hello/views.py~ b/hello/views.py~ index 4d9026cc3..354e993cd 100644 --- a/hello/views.py~ +++ b/hello/views.py~ @@ -1,4 +1,3 @@ -import os import requests from django.shortcuts import render from django.http import HttpResponse @@ -7,11 +6,8 @@ from .models import Greeting # Create your views here. def index(request): - r = requests.get('http://httpbin.org/status/418') - print(r.text) - times= int(os.environ.get('TIMES', 3)) - return HttpResponse('
' + r.text + '
Hello from Python!' * times) - #return render(request, 'index.html') + # return HttpResponse('Hello from Python!') + return render(request, 'index.html') def db(request): From 093914f66058c69726fa78583f7e032a442c1243 Mon Sep 17 00:00:00 2001 From: Kyle Stone Date: Mon, 13 Nov 2017 16:11:48 -0500 Subject: [PATCH 027/143] Revert "Demo Origato Mr. Roboto." This reverts commit 7b995b5b91d41f16b32b140f02d48262833371b8. --- Pipfile | 10 +--- Pipfile.lock | 119 ++---------------------------------------------- hello/views.py | 7 +-- hello/views.py~ | 21 --------- 4 files changed, 9 insertions(+), 148 deletions(-) delete mode 100644 hello/views.py~ diff --git a/Pipfile b/Pipfile index dee8c1ff6..fa4e79d47 100644 --- a/Pipfile +++ b/Pipfile @@ -1,19 +1,13 @@ [[source]] - url = "https://pypi.python.org/simple" verify_ssl = true - [packages] - dj-database-url = "*" django = "*" gunicorn = "*" -"psycopg2" = "*" +psycopg2 = "*" whitenoise = "*" -requests = "*" - [requires] - -python_version = "3.6" +python_version = "3.6" \ No newline at end of file diff --git a/Pipfile.lock b/Pipfile.lock index 2b1a6d6b6..3958b6b66 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,22 +1,8 @@ { "_meta": { "hash": { - "sha256": "5f92a81f5aa11881493a2e0b0a2b80f5230dd044a744462cda905e9e07342442" + "sha256": "c48e4947852b09e706177c0432ea536fe7d0f5f293afef2d4e592035f736121f" }, - "host-environment-markers": { - "implementation_name": "cpython", - "implementation_version": "3.6.3", - "os_name": "posix", - "platform_machine": "x86_64", - "platform_python_implementation": "CPython", - "platform_release": "16.7.0", - "platform_system": "Darwin", - "platform_version": "Darwin Kernel Version 16.7.0: Wed Oct 4 00:17:00 PDT 2017; root:xnu-3789.71.6~1/RELEASE_X86_64", - "python_full_version": "3.6.3", - "python_version": "3.6", - "sys_platform": "darwin" - }, - "pipfile-spec": 6, "requires": { "python_version": "3.6" }, @@ -28,118 +14,23 @@ ] }, "default": { - "certifi": { - "hashes": [ - "sha256:54a07c09c586b0e4c619f02a5e94e36619da8e2b053e20f594348c0611803704", - "sha256:40523d2efb60523e113b44602298f0960e900388cf3bb6043f645cf57ea9e3f5" - ], - "version": "==2017.7.27.1" - }, - "chardet": { - "hashes": [ - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" - ], - "version": "==3.0.4" - }, "dj-database-url": { - "hashes": [ - "sha256:e16d94c382ea0564c48038fa7fe8d9c890ef1ab1a8ec4cb48e732c124b9482fd", - "sha256:a6832d8445ee9d788c5baa48aef8130bf61fdc442f7d9a548424d25cd85c9f08" - ], "version": "==0.4.2" }, "django": { - "hashes": [ - "sha256:75ce405d60f092f6adf904058d023eeea0e6d380f8d9c36134bac73da736023d", - "sha256:8918e392530d8fc6965a56af6504229e7924c27265893f3949aa0529cd1d4b99" - ], - "version": "==1.11.7" + "version": "==1.11.4" }, "gunicorn": { - "hashes": [ - "sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6", - "sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622" - ], "version": "==19.7.1" }, - "idna": { - "hashes": [ - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" - ], - "version": "==2.6" - }, "psycopg2": { - "hashes": [ - "sha256:594aa9a095de16614f703d759e10c018bdffeafce2921b8e80a0e8a0ebbc12e5", - "sha256:1cf5d84290c771eeecb734abe2c6c3120e9837eb12f99474141a862b9061ac51", - "sha256:0344b181e1aea37a58c218ccb0f0f771295de9aa25a625ed076e6996c6530f9e", - "sha256:25250867a4cd1510fb755ef9cb38da3065def999d8e92c44e49a39b9b76bc893", - "sha256:317612d5d0ca4a9f7e42afb2add69b10be360784d21ce4ecfbca19f1f5eadf43", - "sha256:9d6266348b15b4a48623bf4d3e50445d8e581da413644f365805b321703d0fac", - "sha256:ddca39cc55877653b5fcf59976d073e3d58c7c406ef54ae8e61ddf8782867182", - "sha256:988d2ec7560d42ef0ac34b3b97aad14c4f068792f00e1524fa1d3749fe4e4b64", - "sha256:7a9c6c62e6e05df5406e9b5235c31c376a22620ef26715a663cee57083b3c2ea", - "sha256:7a75565181e75ba0b9fb174b58172bf6ea9b4331631cfe7bafff03f3641f5d73", - "sha256:94e4128ba1ea56f02522fffac65520091a9de3f5c00da31539e085e13db4771b", - "sha256:92179bd68c2efe72924a99b6745a9172471931fc296f9bfdf9645b75eebd6344", - "sha256:b9358e203168fef7bfe9f430afaed3a2a624717a1d19c7afa7dfcbd76e3cd95c", - "sha256:009e0bc09a57dbef4b601cb8b46a2abad51f5274c8be4bba276ff2884cd4cc53", - "sha256:d3ac07240e2304181ffdb13c099840b5eb555efc7be9344503c0c03aa681de79", - "sha256:40fa5630cd7d237cd93c4d4b64b9e5ed9273d1cfce55241c7f9066f5db70629d", - "sha256:6c2f1a76a9ebd9ecf7825b9e20860139ca502c2bf1beabf6accf6c9e66a7e0c3", - "sha256:37f54452c7787dbdc0a634ca9773362b91709917f0b365ed14b831f03cbd34ba", - "sha256:8f5942a4daf1ffac42109dc4a72f786af4baa4fa702ede1d7c57b4b696c2e7d6", - "sha256:bf708455cd1e9fa96c05126e89a0c59b200d086c7df7bbafc7d9be769e4149a3", - "sha256:82c40ea3ac1555e0462803380609fbe8b26f52620f3d4f8eb480cfd8ceed8a14", - "sha256:207ba4f9125a0a4200691e82d5eee7ea1485708eabe99a07fc7f08696fae62f4", - "sha256:0cd4c848f0e9d805d531e44973c8f48962e20eb7fc0edac3db4f9dbf9ed5ab82", - "sha256:57baf63aeb2965ca4b52613ce78e968b6d2bde700c97f6a7e8c6c236b51ab83e", - "sha256:2954557393cfc9a5c11a5199c7a78cd9c0c793a047552d27b1636da50d013916", - "sha256:7c31dade89634807196a6b20ced831fbd5bec8a21c4e458ea950c9102c3aa96f", - "sha256:1286dd16d0e46d59fa54582725986704a7a3f3d9aca6c5902a7eceb10c60cb7e", - "sha256:697ff63bc5451e0b0db48ad205151123d25683b3754198be7ab5fcb44334e519", - "sha256:fc993c9331d91766d54757bbc70231e29d5ceb2d1ac08b1570feaa0c38ab9582", - "sha256:9d64fed2681552ed642e9c0cc831a9e95ab91de72b47d0cb68b5bf506ba88647", - "sha256:5c3213be557d0468f9df8fe2487eaf2990d9799202c5ff5cb8d394d09fad9b2a" - ], - "version": "==2.7.3.2" + "version": "==2.7.3.1" }, "pytz": { - "hashes": [ - "sha256:80af0f3008046b9975242012a985f04c5df1f01eed4ec1633d56cc47a75a6a48", - "sha256:feb2365914948b8620347784b6b6da356f31c9d03560259070b2f30cff3d469d", - "sha256:59707844a9825589878236ff2f4e0dc9958511b7ffaae94dc615da07d4a68d33", - "sha256:d0ef5ef55ed3d37854320d4926b04a4cb42a2e88f71da9ddfdacfde8e364f027", - "sha256:c41c62827ce9cafacd6f2f7018e4f83a6f1986e87bfd000b8cfbd4ab5da95f1a", - "sha256:8cc90340159b5d7ced6f2ba77694d946fc975b09f1a51d93f3ce3bb399396f94", - "sha256:dd2e4ca6ce3785c8dd342d1853dd9052b19290d5bf66060846e5dc6b8d6667f7", - "sha256:699d18a2a56f19ee5698ab1123bbcc1d269d061996aeb1eda6d89248d3542b82", - "sha256:fae4cffc040921b8a2d60c6cf0b5d662c1190fe54d718271db4eb17d44a185b7" - ], - "version": "==2017.3" - }, - "requests": { - "hashes": [ - "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", - "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" - ], - "version": "==2.18.4" - }, - "urllib3": { - "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" - ], - "version": "==1.22" + "version": "==2017.2" }, "whitenoise": { - "hashes": [ - "sha256:15f43b2e701821b95c9016cf469d29e2a546cb1c7dead584ba82c36f843995cf", - "sha256:9d81515f2b5b27051910996e1e860b1332e354d9e7bcf30c98f21dcb6713e0dd" - ], - "version": "==3.3.1" + "version": "==3.3.0" } }, "develop": {} diff --git a/hello/views.py b/hello/views.py index 3e882edb9..8558d8451 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,4 +1,3 @@ -import requests from django.shortcuts import render from django.http import HttpResponse @@ -6,10 +5,8 @@ # Create your views here. def index(request): - r = requests.get('http://httpbin.org/status/418') - print(r.text) - return HttpResponse('
' + r.text + '
Hello from Python!') - #return render(request, 'index.html') + # return HttpResponse('Hello from Python!') + return render(request, 'index.html') def db(request): diff --git a/hello/views.py~ b/hello/views.py~ deleted file mode 100644 index 354e993cd..000000000 --- a/hello/views.py~ +++ /dev/null @@ -1,21 +0,0 @@ -import requests -from django.shortcuts import render -from django.http import HttpResponse - -from .models import Greeting - -# Create your views here. -def index(request): - # return HttpResponse('Hello from Python!') - return render(request, 'index.html') - - -def db(request): - - greeting = Greeting() - greeting.save() - - greetings = Greeting.objects.all() - - return render(request, 'db.html', {'greetings': greetings}) - From 180cbfb1d26dd4bf66248ad385d5134ff07126d0 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 11 Dec 2017 11:52:33 -0500 Subject: [PATCH 028/143] updates Signed-off-by: Kenneth Reitz --- Pipfile | 11 ++-- Pipfile.lock | 91 ++++++++++++++++++++++++++-- Procfile | 2 +- app.json | 7 ++- gettingstarted/heroku_test_runner.py | 55 ----------------- gettingstarted/settings.py | 73 +++++++++------------- hello/templates/index.html | 2 +- 7 files changed, 128 insertions(+), 113 deletions(-) delete mode 100644 gettingstarted/heroku_test_runner.py diff --git a/Pipfile b/Pipfile index fa4e79d47..70ca30fda 100644 --- a/Pipfile +++ b/Pipfile @@ -1,13 +1,16 @@ [[source]] + url = "https://pypi.python.org/simple" verify_ssl = true + [packages] -dj-database-url = "*" + django = "*" gunicorn = "*" -psycopg2 = "*" -whitenoise = "*" +django-heroku = "*" + [requires] -python_version = "3.6" \ No newline at end of file + +python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 3958b6b66..397a1c9d2 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,8 +1,22 @@ { "_meta": { "hash": { - "sha256": "c48e4947852b09e706177c0432ea536fe7d0f5f293afef2d4e592035f736121f" + "sha256": "7843aa61794626156c5dbfa26d6be61df24889c396f04a8dead353d23e2899d6" }, + "host-environment-markers": { + "implementation_name": "cpython", + "implementation_version": "3.6.3", + "os_name": "posix", + "platform_machine": "x86_64", + "platform_python_implementation": "CPython", + "platform_release": "17.3.0", + "platform_system": "Darwin", + "platform_version": "Darwin Kernel Version 17.3.0: Thu Nov 9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64", + "python_full_version": "3.6.3", + "python_version": "3.6", + "sys_platform": "darwin" + }, + "pipfile-spec": 6, "requires": { "python_version": "3.6" }, @@ -15,22 +29,89 @@ }, "default": { "dj-database-url": { + "hashes": [ + "sha256:e16d94c382ea0564c48038fa7fe8d9c890ef1ab1a8ec4cb48e732c124b9482fd", + "sha256:a6832d8445ee9d788c5baa48aef8130bf61fdc442f7d9a548424d25cd85c9f08" + ], "version": "==0.4.2" }, "django": { - "version": "==1.11.4" + "hashes": [ + "sha256:af18618ce3291be5092893d8522fe3919661bf3a1fb60e3858ae74865a4f07c2", + "sha256:9614851d4a7ff8cbd32b73c6076441f377c45a5bbff7e771798fb02c43c31f47" + ], + "version": "==2.0" + }, + "django-heroku": { + "hashes": [ + "sha256:193bacbe644a607642f6b60acd0a382d6abf4a1f7578f8d3eb10659457efe904", + "sha256:af6c723872553b7427121a865eb9fce70d566b9ad26d7defcdcd03a8acea56c8" + ], + "version": "==0.1.0" }, "gunicorn": { + "hashes": [ + "sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6", + "sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622" + ], "version": "==19.7.1" }, "psycopg2": { - "version": "==2.7.3.1" + "hashes": [ + "sha256:594aa9a095de16614f703d759e10c018bdffeafce2921b8e80a0e8a0ebbc12e5", + "sha256:1cf5d84290c771eeecb734abe2c6c3120e9837eb12f99474141a862b9061ac51", + "sha256:0344b181e1aea37a58c218ccb0f0f771295de9aa25a625ed076e6996c6530f9e", + "sha256:25250867a4cd1510fb755ef9cb38da3065def999d8e92c44e49a39b9b76bc893", + "sha256:317612d5d0ca4a9f7e42afb2add69b10be360784d21ce4ecfbca19f1f5eadf43", + "sha256:9d6266348b15b4a48623bf4d3e50445d8e581da413644f365805b321703d0fac", + "sha256:ddca39cc55877653b5fcf59976d073e3d58c7c406ef54ae8e61ddf8782867182", + "sha256:988d2ec7560d42ef0ac34b3b97aad14c4f068792f00e1524fa1d3749fe4e4b64", + "sha256:7a9c6c62e6e05df5406e9b5235c31c376a22620ef26715a663cee57083b3c2ea", + "sha256:7a75565181e75ba0b9fb174b58172bf6ea9b4331631cfe7bafff03f3641f5d73", + "sha256:94e4128ba1ea56f02522fffac65520091a9de3f5c00da31539e085e13db4771b", + "sha256:92179bd68c2efe72924a99b6745a9172471931fc296f9bfdf9645b75eebd6344", + "sha256:b9358e203168fef7bfe9f430afaed3a2a624717a1d19c7afa7dfcbd76e3cd95c", + "sha256:009e0bc09a57dbef4b601cb8b46a2abad51f5274c8be4bba276ff2884cd4cc53", + "sha256:d3ac07240e2304181ffdb13c099840b5eb555efc7be9344503c0c03aa681de79", + "sha256:40fa5630cd7d237cd93c4d4b64b9e5ed9273d1cfce55241c7f9066f5db70629d", + "sha256:6c2f1a76a9ebd9ecf7825b9e20860139ca502c2bf1beabf6accf6c9e66a7e0c3", + "sha256:37f54452c7787dbdc0a634ca9773362b91709917f0b365ed14b831f03cbd34ba", + "sha256:8f5942a4daf1ffac42109dc4a72f786af4baa4fa702ede1d7c57b4b696c2e7d6", + "sha256:bf708455cd1e9fa96c05126e89a0c59b200d086c7df7bbafc7d9be769e4149a3", + "sha256:82c40ea3ac1555e0462803380609fbe8b26f52620f3d4f8eb480cfd8ceed8a14", + "sha256:207ba4f9125a0a4200691e82d5eee7ea1485708eabe99a07fc7f08696fae62f4", + "sha256:0cd4c848f0e9d805d531e44973c8f48962e20eb7fc0edac3db4f9dbf9ed5ab82", + "sha256:57baf63aeb2965ca4b52613ce78e968b6d2bde700c97f6a7e8c6c236b51ab83e", + "sha256:2954557393cfc9a5c11a5199c7a78cd9c0c793a047552d27b1636da50d013916", + "sha256:7c31dade89634807196a6b20ced831fbd5bec8a21c4e458ea950c9102c3aa96f", + "sha256:1286dd16d0e46d59fa54582725986704a7a3f3d9aca6c5902a7eceb10c60cb7e", + "sha256:697ff63bc5451e0b0db48ad205151123d25683b3754198be7ab5fcb44334e519", + "sha256:fc993c9331d91766d54757bbc70231e29d5ceb2d1ac08b1570feaa0c38ab9582", + "sha256:9d64fed2681552ed642e9c0cc831a9e95ab91de72b47d0cb68b5bf506ba88647", + "sha256:5c3213be557d0468f9df8fe2487eaf2990d9799202c5ff5cb8d394d09fad9b2a" + ], + "version": "==2.7.3.2" }, "pytz": { - "version": "==2017.2" + "hashes": [ + "sha256:80af0f3008046b9975242012a985f04c5df1f01eed4ec1633d56cc47a75a6a48", + "sha256:feb2365914948b8620347784b6b6da356f31c9d03560259070b2f30cff3d469d", + "sha256:59707844a9825589878236ff2f4e0dc9958511b7ffaae94dc615da07d4a68d33", + "sha256:d0ef5ef55ed3d37854320d4926b04a4cb42a2e88f71da9ddfdacfde8e364f027", + "sha256:c41c62827ce9cafacd6f2f7018e4f83a6f1986e87bfd000b8cfbd4ab5da95f1a", + "sha256:8cc90340159b5d7ced6f2ba77694d946fc975b09f1a51d93f3ce3bb399396f94", + "sha256:dd2e4ca6ce3785c8dd342d1853dd9052b19290d5bf66060846e5dc6b8d6667f7", + "sha256:699d18a2a56f19ee5698ab1123bbcc1d269d061996aeb1eda6d89248d3542b82", + "sha256:fae4cffc040921b8a2d60c6cf0b5d662c1190fe54d718271db4eb17d44a185b7" + ], + "version": "==2017.3" }, "whitenoise": { - "version": "==3.3.0" + "hashes": [ + "sha256:15f43b2e701821b95c9016cf469d29e2a546cb1c7dead584ba82c36f843995cf", + "sha256:9d81515f2b5b27051910996e1e860b1332e354d9e7bcf30c98f21dcb6713e0dd" + ], + "version": "==3.3.1" } }, "develop": {} diff --git a/Procfile b/Procfile index 47a27c07f..b6f89307b 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: gunicorn gettingstarted.wsgi --log-file - +web: gunicorn gettingstarted.wsgi diff --git a/app.json b/app.json index 8cba47e35..636a86a8d 100644 --- a/app.json +++ b/app.json @@ -5,6 +5,11 @@ "repository": "https://github.com/heroku/python-getting-started", "keywords": ["python", "django" ], "addons": [ "heroku-postgresql" ], + "env": { + "SECRET_KEY": { + "description": "The secret key for the Django application.", + "generator": "secret" + }, "environments": { "test": { "scripts": { @@ -13,4 +18,4 @@ } } } -} +} \ No newline at end of file diff --git a/gettingstarted/heroku_test_runner.py b/gettingstarted/heroku_test_runner.py deleted file mode 100644 index 7a8a1447a..000000000 --- a/gettingstarted/heroku_test_runner.py +++ /dev/null @@ -1,55 +0,0 @@ -import os - -from django.test.runner import DiscoverRunner - -""" -WARNING: WHEN USED INCORRECTLY THIS TEST RUNNER WILL DROP ALL TABLES IN YOUR PRODUCTION -DATABASE!!! - -Heroku does not give users createdb/dropdb permissions, therefore Heroku CI cannot run tests for django. -In order to fix this, use this test runner instead which attempts to minimally override the -default test runner by a) forcing keepdb=True to stop database create/drop, and b) by dropping all -tables after a test run and resetting the database to its initial blank state. - -Usage: - -1. In your django test settings file add the following two lines to ensure that the test -database name is the same as the Heroku provided database name. - -DATABASES['default'] = env.db('DATABASE_URL') # or whatever you use to load the Heroku database settings -DATABASES['default']['TEST'] = {'NAME': DATABASES['default']['NAME']} - -2. Set the testrunner to this file -TEST_RUNNER = 'your_modules.HerokuDiscoverRunner' - -3. Set an environment variable on heroku CI of IS_HEROKU_TEST=1 to enable this runner, otherwise -the runner will exit as a safety measure. -""" - -class HerokuDiscoverRunner(DiscoverRunner): - def setup_databases(self, **kwargs): - if not os.environ.get('IS_HEROKU_TEST'): - raise ValueError( - "The IS_HEROKU_TEST env variable must be set to enable this. WARNING: " - "This test runner will wipe all tables in the database it targets!") - self.keepdb = True - return super(HerokuDiscoverRunner, self).setup_databases(**kwargs) - - def _wipe_tables(self, connection): - with connection.cursor() as cursor: - cursor.execute( - """ - DROP SCHEMA public CASCADE; - CREATE SCHEMA public; - GRANT ALL ON SCHEMA public TO postgres; - GRANT ALL ON SCHEMA public TO public; - COMMENT ON SCHEMA public IS 'standard public schema'; - """ - ) - - def teardown_databases(self, old_config, **kwargs): - self.keepdb = True - for connection, old_name, destroy in old_config: - if destroy: - self._wipe_tables(connection) - super(HerokuDiscoverRunner, self).teardown_databases(old_config, **kwargs) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index ab15fea8b..b23e28bc2 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -1,38 +1,38 @@ """ -Django settings for gettingstarted project, on Heroku. For more info, see: -https://github.com/heroku/heroku-django-template +Django settings for gettingstarted project. + +Generated by 'django-admin startproject' using Django 2.0. For more information on this file, see -https://docs.djangoproject.com/en/1.8/topics/settings/ +https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.8/ref/settings/ +https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os -import dj_database_url +import django_heroku # Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(__file__)) -PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ -# SECURITY WARNING: change this before deploying to production! -SECRET_KEY = 'i+acxn5(akgsn!sr4^qgf(^m&*@+g1@u^t@=8s@axc41ml*f=s' +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'CHANGE_ME!!!! (P.S. the SECRET_KEY environment variable will be used, if set, instead).' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -TEST_RUNNER = 'gettingstarted.heroku_test_runner.HerokuDiscoverRunner' +ALLOWED_HOSTS = [] # Application definition -INSTALLED_APPS = ( +INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -40,21 +40,17 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'hello' -) +] -MIDDLEWARE_CLASSES = ( - # Simplified static file serving. - # https://warehouse.python.org/project/whitenoise/ - 'whitenoise.middleware.WhiteNoiseMiddleware', +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'django.middleware.security.SecurityMiddleware', -) +] ROOT_URLCONF = 'gettingstarted.urls' @@ -64,7 +60,6 @@ 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { - 'debug': True, 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', @@ -79,7 +74,7 @@ # Database -# https://docs.djangoproject.com/en/1.9/ref/settings/#databases +# https://docs.djangoproject.com/en/2.0/ref/settings/#databases DATABASES = { 'default': { @@ -88,8 +83,9 @@ } } + # Password validation -# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -106,39 +102,24 @@ }, ] + # Internationalization -# https://docs.djangoproject.com/en/1.8/topics/i18n/ +# https://docs.djangoproject.com/en/2.0/topics/i18n/ LANGUAGE_CODE = 'en-us' + TIME_ZONE = 'UTC' -USE_I18N = True -USE_L10N = True -USE_TZ = True +USE_I18N = True -# Update database configuration with $DATABASE_URL. -db_from_env = dj_database_url.config(conn_max_age=500) -DATABASES['default'].update(db_from_env) -DATABASES['default']['TEST'] = {'NAME': DATABASES['default']['NAME']} +USE_L10N = True -# Honor the 'X-Forwarded-Proto' header for request.is_secure() -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +USE_TZ = True -# Allow all host headers -ALLOWED_HOSTS = ['*'] # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.8/howto/static-files/ +# https://docs.djangoproject.com/en/2.0/howto/static-files/ -STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles') STATIC_URL = '/static/' -# Extra places for collectstatic to find static files. -STATICFILES_DIRS = ( - os.path.join(PROJECT_ROOT, 'static'), -) - -# Simplified static file serving. -# https://warehouse.python.org/project/whitenoise/ -STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' - +django_heroku.settings(locals()) \ No newline at end of file diff --git a/hello/templates/index.html b/hello/templates/index.html index 3c7236392..8af29028b 100644 --- a/hello/templates/index.html +++ b/hello/templates/index.html @@ -25,7 +25,7 @@

How this sample app work
  • This app was deployed to Heroku, either using Git or by using Heroku Button on the repository.
  • -
  • When Heroku received the source code, it fetched all the dependencies in the requirements.txt file, creating a deployable slug.
  • +
  • When Heroku received the source code, it fetched all the dependencies in the Pipfile, creating a deployable slug.
  • The platform then spins up a dyno, a lightweight container that provides an isolated environment in which the slug can be mounted and executed.
  • You can scale your app, manage it, and deploy over 150 add-on services, from the Dashboard or CLI.
From d5d23126225bffcabb052a33a7a40ce99558487e Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 11 Dec 2017 11:54:16 -0500 Subject: [PATCH 029/143] app.json Signed-off-by: Kenneth Reitz --- app.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app.json b/app.json index 636a86a8d..8721c4994 100644 --- a/app.json +++ b/app.json @@ -9,7 +9,8 @@ "SECRET_KEY": { "description": "The secret key for the Django application.", "generator": "secret" - }, + } + }, "environments": { "test": { "scripts": { @@ -18,4 +19,4 @@ } } } -} \ No newline at end of file +} From f56b90499ec11e1c9576da2f8c7331300e189db3 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 11 Dec 2017 12:01:49 -0500 Subject: [PATCH 030/143] fix urls for django 2.0 Signed-off-by: Kenneth Reitz --- gettingstarted/urls.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index 608147ae5..36492ed3c 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -1,4 +1,5 @@ from django.conf.urls import include, url +from django.urls import path from django.contrib import admin admin.autodiscover() @@ -12,5 +13,5 @@ urlpatterns = [ url(r'^$', hello.views.index, name='index'), url(r'^db', hello.views.db, name='db'), - url(r'^admin/', include(admin.site.urls)), + path('admin/', admin.site.urls), ] From a9dee3d81175928596c5a2119755261d48e773ca Mon Sep 17 00:00:00 2001 From: Kevin Brolly Date: Mon, 15 Oct 2018 15:38:36 +0100 Subject: [PATCH 031/143] Updated defaults --- gettingstarted/settings.py | 16 ++++++++-------- hello/models.py | 8 +++++++- hello/views.py | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index b23e28bc2..675680911 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -39,6 +39,7 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.gis', 'hello' ] @@ -76,13 +77,12 @@ # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } -} - +import dj_database_url +DATABASES = {'default': dj_database_url.config( + engine='django.contrib.gis.db.backends.postgis', + conn_max_age=500, + require_ssl=True +)} # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators @@ -122,4 +122,4 @@ STATIC_URL = '/static/' -django_heroku.settings(locals()) \ No newline at end of file +django_heroku.settings(locals()) diff --git a/hello/models.py b/hello/models.py index 89d76fd1b..ec0cc93cb 100644 --- a/hello/models.py +++ b/hello/models.py @@ -1,5 +1,11 @@ -from django.db import models +from django.contrib.gis.db import models # Create your models here. class Greeting(models.Model): when = models.DateTimeField('date created', auto_now_add=True) + + +class TestGeo(models.Model): + geometry = models.GeometryField() + point = models.PointField() + mpoly = models.MultiPolygonField() diff --git a/hello/views.py b/hello/views.py index 8558d8451..db2611ac0 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,7 +1,7 @@ from django.shortcuts import render from django.http import HttpResponse -from .models import Greeting +from .models import Greeting, TestGeo # Create your views here. def index(request): From 44bc12271a3ec48baa3cde4ac84318570d00ff44 Mon Sep 17 00:00:00 2001 From: Kevin Brolly Date: Mon, 15 Oct 2018 15:42:28 +0100 Subject: [PATCH 032/143] Updated settings --- gettingstarted/settings.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 675680911..fcb04e27c 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -78,11 +78,7 @@ # https://docs.djangoproject.com/en/2.0/ref/settings/#databases import dj_database_url -DATABASES = {'default': dj_database_url.config( - engine='django.contrib.gis.db.backends.postgis', - conn_max_age=500, - require_ssl=True -)} +DATABASES = {'default': dj_database_url.config(engine='django.contrib.gis.db.backends.postgis')} # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators From 0db60dc2c92bc31f34025d1d87fc91138b1e25fd Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 16 Aug 2018 15:36:11 -0500 Subject: [PATCH 033/143] add requirements.txt --- requirements.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..dc2c8ffc7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +dj-database-url==0.5.0 +Django==2.1 +django-heroku==0.3.1 +gunicorn==19.9.0 +psycopg2==2.7.5 +pytz==2018.5 +whitenoise==4.0 From 15ff50d6e3bed887e4da44ec698403cbc7f18af2 Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 16 Aug 2018 15:37:28 -0500 Subject: [PATCH 034/143] remove pipfile --- Pipfile | 16 ------- Pipfile.lock | 118 --------------------------------------------------- 2 files changed, 134 deletions(-) delete mode 100644 Pipfile delete mode 100644 Pipfile.lock diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 70ca30fda..000000000 --- a/Pipfile +++ /dev/null @@ -1,16 +0,0 @@ -[[source]] - -url = "https://pypi.python.org/simple" -verify_ssl = true - - -[packages] - -django = "*" -gunicorn = "*" -django-heroku = "*" - - -[requires] - -python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 397a1c9d2..000000000 --- a/Pipfile.lock +++ /dev/null @@ -1,118 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "7843aa61794626156c5dbfa26d6be61df24889c396f04a8dead353d23e2899d6" - }, - "host-environment-markers": { - "implementation_name": "cpython", - "implementation_version": "3.6.3", - "os_name": "posix", - "platform_machine": "x86_64", - "platform_python_implementation": "CPython", - "platform_release": "17.3.0", - "platform_system": "Darwin", - "platform_version": "Darwin Kernel Version 17.3.0: Thu Nov 9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64", - "python_full_version": "3.6.3", - "python_version": "3.6", - "sys_platform": "darwin" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.6" - }, - "sources": [ - { - "url": "https://pypi.python.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "dj-database-url": { - "hashes": [ - "sha256:e16d94c382ea0564c48038fa7fe8d9c890ef1ab1a8ec4cb48e732c124b9482fd", - "sha256:a6832d8445ee9d788c5baa48aef8130bf61fdc442f7d9a548424d25cd85c9f08" - ], - "version": "==0.4.2" - }, - "django": { - "hashes": [ - "sha256:af18618ce3291be5092893d8522fe3919661bf3a1fb60e3858ae74865a4f07c2", - "sha256:9614851d4a7ff8cbd32b73c6076441f377c45a5bbff7e771798fb02c43c31f47" - ], - "version": "==2.0" - }, - "django-heroku": { - "hashes": [ - "sha256:193bacbe644a607642f6b60acd0a382d6abf4a1f7578f8d3eb10659457efe904", - "sha256:af6c723872553b7427121a865eb9fce70d566b9ad26d7defcdcd03a8acea56c8" - ], - "version": "==0.1.0" - }, - "gunicorn": { - "hashes": [ - "sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6", - "sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622" - ], - "version": "==19.7.1" - }, - "psycopg2": { - "hashes": [ - "sha256:594aa9a095de16614f703d759e10c018bdffeafce2921b8e80a0e8a0ebbc12e5", - "sha256:1cf5d84290c771eeecb734abe2c6c3120e9837eb12f99474141a862b9061ac51", - "sha256:0344b181e1aea37a58c218ccb0f0f771295de9aa25a625ed076e6996c6530f9e", - "sha256:25250867a4cd1510fb755ef9cb38da3065def999d8e92c44e49a39b9b76bc893", - "sha256:317612d5d0ca4a9f7e42afb2add69b10be360784d21ce4ecfbca19f1f5eadf43", - "sha256:9d6266348b15b4a48623bf4d3e50445d8e581da413644f365805b321703d0fac", - "sha256:ddca39cc55877653b5fcf59976d073e3d58c7c406ef54ae8e61ddf8782867182", - "sha256:988d2ec7560d42ef0ac34b3b97aad14c4f068792f00e1524fa1d3749fe4e4b64", - "sha256:7a9c6c62e6e05df5406e9b5235c31c376a22620ef26715a663cee57083b3c2ea", - "sha256:7a75565181e75ba0b9fb174b58172bf6ea9b4331631cfe7bafff03f3641f5d73", - "sha256:94e4128ba1ea56f02522fffac65520091a9de3f5c00da31539e085e13db4771b", - "sha256:92179bd68c2efe72924a99b6745a9172471931fc296f9bfdf9645b75eebd6344", - "sha256:b9358e203168fef7bfe9f430afaed3a2a624717a1d19c7afa7dfcbd76e3cd95c", - "sha256:009e0bc09a57dbef4b601cb8b46a2abad51f5274c8be4bba276ff2884cd4cc53", - "sha256:d3ac07240e2304181ffdb13c099840b5eb555efc7be9344503c0c03aa681de79", - "sha256:40fa5630cd7d237cd93c4d4b64b9e5ed9273d1cfce55241c7f9066f5db70629d", - "sha256:6c2f1a76a9ebd9ecf7825b9e20860139ca502c2bf1beabf6accf6c9e66a7e0c3", - "sha256:37f54452c7787dbdc0a634ca9773362b91709917f0b365ed14b831f03cbd34ba", - "sha256:8f5942a4daf1ffac42109dc4a72f786af4baa4fa702ede1d7c57b4b696c2e7d6", - "sha256:bf708455cd1e9fa96c05126e89a0c59b200d086c7df7bbafc7d9be769e4149a3", - "sha256:82c40ea3ac1555e0462803380609fbe8b26f52620f3d4f8eb480cfd8ceed8a14", - "sha256:207ba4f9125a0a4200691e82d5eee7ea1485708eabe99a07fc7f08696fae62f4", - "sha256:0cd4c848f0e9d805d531e44973c8f48962e20eb7fc0edac3db4f9dbf9ed5ab82", - "sha256:57baf63aeb2965ca4b52613ce78e968b6d2bde700c97f6a7e8c6c236b51ab83e", - "sha256:2954557393cfc9a5c11a5199c7a78cd9c0c793a047552d27b1636da50d013916", - "sha256:7c31dade89634807196a6b20ced831fbd5bec8a21c4e458ea950c9102c3aa96f", - "sha256:1286dd16d0e46d59fa54582725986704a7a3f3d9aca6c5902a7eceb10c60cb7e", - "sha256:697ff63bc5451e0b0db48ad205151123d25683b3754198be7ab5fcb44334e519", - "sha256:fc993c9331d91766d54757bbc70231e29d5ceb2d1ac08b1570feaa0c38ab9582", - "sha256:9d64fed2681552ed642e9c0cc831a9e95ab91de72b47d0cb68b5bf506ba88647", - "sha256:5c3213be557d0468f9df8fe2487eaf2990d9799202c5ff5cb8d394d09fad9b2a" - ], - "version": "==2.7.3.2" - }, - "pytz": { - "hashes": [ - "sha256:80af0f3008046b9975242012a985f04c5df1f01eed4ec1633d56cc47a75a6a48", - "sha256:feb2365914948b8620347784b6b6da356f31c9d03560259070b2f30cff3d469d", - "sha256:59707844a9825589878236ff2f4e0dc9958511b7ffaae94dc615da07d4a68d33", - "sha256:d0ef5ef55ed3d37854320d4926b04a4cb42a2e88f71da9ddfdacfde8e364f027", - "sha256:c41c62827ce9cafacd6f2f7018e4f83a6f1986e87bfd000b8cfbd4ab5da95f1a", - "sha256:8cc90340159b5d7ced6f2ba77694d946fc975b09f1a51d93f3ce3bb399396f94", - "sha256:dd2e4ca6ce3785c8dd342d1853dd9052b19290d5bf66060846e5dc6b8d6667f7", - "sha256:699d18a2a56f19ee5698ab1123bbcc1d269d061996aeb1eda6d89248d3542b82", - "sha256:fae4cffc040921b8a2d60c6cf0b5d662c1190fe54d718271db4eb17d44a185b7" - ], - "version": "==2017.3" - }, - "whitenoise": { - "hashes": [ - "sha256:15f43b2e701821b95c9016cf469d29e2a546cb1c7dead584ba82c36f843995cf", - "sha256:9d81515f2b5b27051910996e1e860b1332e354d9e7bcf30c98f21dcb6713e0dd" - ], - "version": "==3.3.1" - } - }, - "develop": {} -} From 63d304958debdfe9997118acf5de00ebfafc601a Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 16 Aug 2018 15:37:56 -0500 Subject: [PATCH 035/143] update readme --- .gitignore | 1 + README.md | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f95d164a6..4875ad398 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ venv staticfiles .env db.sqlite3 +getting-started/* \ No newline at end of file diff --git a/README.md b/README.md index 23ff5a077..af83d0dda 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,14 @@ This application supports the [Getting Started with Python on Heroku](https://de ## Running Locally -Make sure you have Python [installed properly](http://install.python-guide.org). Also, install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) and [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). +Make sure you have Python 3.7 [installed locally](http://install.python-guide.org). To push to Heroku, you'll need to install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli), as well as [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). ```sh $ git clone git@github.com:heroku/python-getting-started.git $ cd python-getting-started -$ pipenv install +$ python3 -m venv getting-started +$ pip install -r requirements.txt $ createdb python_getting_started From 8e15aa84a0c40f827d9937c3fd68ae5ca0036e59 Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 16 Aug 2018 15:57:16 -0500 Subject: [PATCH 036/143] add runtime to specify version --- runtime.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 runtime.txt diff --git a/runtime.txt b/runtime.txt new file mode 100644 index 000000000..b16fb5e0e --- /dev/null +++ b/runtime.txt @@ -0,0 +1 @@ +python-3.7.0 \ No newline at end of file From 5d4e476b90a3ba5f7bfcf306b022f3f6096c6cad Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Fri, 17 Aug 2018 07:58:56 -0500 Subject: [PATCH 037/143] convert git clone to https method --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index af83d0dda..8cbdb7f82 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This application supports the [Getting Started with Python on Heroku](https://de Make sure you have Python 3.7 [installed locally](http://install.python-guide.org). To push to Heroku, you'll need to install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli), as well as [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). ```sh -$ git clone git@github.com:heroku/python-getting-started.git +$ git clone https://github.com/heroku/python-getting-started.git $ cd python-getting-started $ python3 -m venv getting-started From 09e94e53832dfafce3b7c160523e6be34d4ca0c5 Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Fri, 17 Aug 2018 13:26:20 -0500 Subject: [PATCH 038/143] remove explicit requirement versions --- requirements.txt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index dc2c8ffc7..4af6a3765 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,3 @@ -dj-database-url==0.5.0 -Django==2.1 -django-heroku==0.3.1 -gunicorn==19.9.0 -psycopg2==2.7.5 -pytz==2018.5 -whitenoise==4.0 +django +gunicorn +django-heroku \ No newline at end of file From 33d373d662b130a14d0a2f781287593dafd92229 Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Tue, 18 Sep 2018 09:50:49 -0500 Subject: [PATCH 039/143] add PR template --- .github/PULL_REQUEST_TEMPLATE.MD | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.MD diff --git a/.github/PULL_REQUEST_TEMPLATE.MD b/.github/PULL_REQUEST_TEMPLATE.MD new file mode 100644 index 000000000..eb8203925 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.MD @@ -0,0 +1,10 @@ + From cdc4e0a368f2b4edd1c509e19d6435d9d3745e1f Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Wed, 17 Oct 2018 19:17:23 -0500 Subject: [PATCH 040/143] blacken getting started guide --- gettingstarted/settings.py | 83 ++++++++++++++++++-------------------- gettingstarted/urls.py | 7 ++-- gettingstarted/wsgi.py | 3 +- 3 files changed, 46 insertions(+), 47 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index fcb04e27c..9e33e064b 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -22,7 +22,7 @@ # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'CHANGE_ME!!!! (P.S. the SECRET_KEY environment variable will be used, if set, instead).' +SECRET_KEY = "CHANGE_ME!!!! (P.S. the SECRET_KEY environment variable will be used, if set, instead)." # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -33,78 +33,75 @@ # Application definition INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.gis', - 'hello' + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.gis", + "hello", ] MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = 'gettingstarted.urls' +ROOT_URLCONF = "gettingstarted.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ] }, - }, + } ] -WSGI_APPLICATION = 'gettingstarted.wsgi.application' +WSGI_APPLICATION = "gettingstarted.wsgi.application" # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases import dj_database_url -DATABASES = {'default': dj_database_url.config(engine='django.contrib.gis.db.backends.postgis')} + +DATABASES = { + "default": dj_database_url.config(engine="django.contrib.gis.db.backends.postgis") +} # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" }, + {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, + {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, + {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, ] # Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" -TIME_ZONE = 'UTC' +TIME_ZONE = "UTC" USE_I18N = True @@ -116,6 +113,6 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ -STATIC_URL = '/static/' +STATIC_URL = "/static/" django_heroku.settings(locals()) diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index 36492ed3c..bd475661f 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -2,6 +2,7 @@ from django.urls import path from django.contrib import admin + admin.autodiscover() import hello.views @@ -11,7 +12,7 @@ # url(r'^blog/', include('blog.urls')), urlpatterns = [ - url(r'^$', hello.views.index, name='index'), - url(r'^db', hello.views.db, name='db'), - path('admin/', admin.site.urls), + url(r"^$", hello.views.index, name="index"), + url(r"^db", hello.views.db, name="db"), + path("admin/", admin.site.urls), ] diff --git a/gettingstarted/wsgi.py b/gettingstarted/wsgi.py index feb0af46f..3c528d7ce 100644 --- a/gettingstarted/wsgi.py +++ b/gettingstarted/wsgi.py @@ -4,10 +4,11 @@ It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ """ import os + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gettingstarted.settings") from django.core.wsgi import get_wsgi_application From f70b997f563abcc1d02ec3a3f507b2fbe392b3dc Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 18 Oct 2018 11:52:10 -0500 Subject: [PATCH 041/143] update urls to 2.1 --- gettingstarted/urls.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index bd475661f..13b759582 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -1,5 +1,4 @@ -from django.conf.urls import include, url -from django.urls import path +from django.urls import path, include from django.contrib import admin @@ -7,12 +6,16 @@ import hello.views -# Examples: -# url(r'^$', 'gettingstarted.views.home', name='home'), -# url(r'^blog/', include('blog.urls')), +# To add a new path, first import the app: +# import blog +# +# Then add the new path: +# path('blog/', blog.urls, name="blog") +# +# Learn more here: https://docs.djangoproject.com/en/2.1/topics/http/urls/ urlpatterns = [ - url(r"^$", hello.views.index, name="index"), - url(r"^db", hello.views.db, name="db"), + path("", hello.views.index, name="index"), + path("db/", hello.views.db, name="db"), path("admin/", admin.site.urls), ] From 26a9055a601c41be6577ae3f1d0b1b69444cb2bc Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 18 Oct 2018 15:28:39 -0500 Subject: [PATCH 042/143] blacken hello --- gettingstarted/settings.py | 6 ++++-- hello/models.py | 10 ++-------- hello/tests.py | 5 +++-- hello/views.py | 7 +++---- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 9e33e064b..0de188d04 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -39,7 +39,6 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - "django.contrib.gis", "hello", ] @@ -80,7 +79,10 @@ import dj_database_url DATABASES = { - "default": dj_database_url.config(engine="django.contrib.gis.db.backends.postgis") + "default": { + "ENGINE" : "django.db.backends.sqlite3", + "NAME": os.path.join(BASE_DIR, "db.sqlite3") + } } # Password validation diff --git a/hello/models.py b/hello/models.py index ec0cc93cb..8229092ef 100644 --- a/hello/models.py +++ b/hello/models.py @@ -1,11 +1,5 @@ -from django.contrib.gis.db import models +from django.db import models # Create your models here. class Greeting(models.Model): - when = models.DateTimeField('date created', auto_now_add=True) - - -class TestGeo(models.Model): - geometry = models.GeometryField() - point = models.PointField() - mpoly = models.MultiPolygonField() + when = models.DateTimeField("date created", auto_now_add=True) diff --git a/hello/tests.py b/hello/tests.py index 1d69113fe..9b06366a5 100644 --- a/hello/tests.py +++ b/hello/tests.py @@ -3,6 +3,7 @@ from .views import index + class SimpleTest(TestCase): def setUp(self): # Every test needs access to the request factory. @@ -10,9 +11,9 @@ def setUp(self): def test_details(self): # Create an instance of a GET request. - request = self.factory.get('/') + request = self.factory.get("/") request.user = AnonymousUser() # Test my_view() as if it were deployed at /customer/details response = index(request) - self.assertEqual(response.status_code, 200) \ No newline at end of file + self.assertEqual(response.status_code, 200) diff --git a/hello/views.py b/hello/views.py index db2611ac0..c2480724b 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,12 +1,12 @@ from django.shortcuts import render from django.http import HttpResponse -from .models import Greeting, TestGeo +from .models import Greeting # Create your views here. def index(request): # return HttpResponse('Hello from Python!') - return render(request, 'index.html') + return render(request, "index.html") def db(request): @@ -16,5 +16,4 @@ def db(request): greetings = Greeting.objects.all() - return render(request, 'db.html', {'greetings': greetings}) - + return render(request, "db.html", {"greetings": greetings}) From dd8436a9dbe6e208697e809aef9925034aa4fa7b Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 18 Oct 2018 16:27:33 -0500 Subject: [PATCH 043/143] update static root for whitenoise --- gettingstarted/settings.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 0de188d04..9ea552a0c 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -76,8 +76,6 @@ # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases -import dj_database_url - DATABASES = { "default": { "ENGINE" : "django.db.backends.sqlite3", @@ -115,6 +113,7 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATIC_URL = "/static/" django_heroku.settings(locals()) From 5df7f0303ccc9c021ce1d84d12023b360b1c50ed Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 18 Oct 2018 16:44:07 -0500 Subject: [PATCH 044/143] migrate on deploy --- Procfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Procfile b/Procfile index b6f89307b..2b2dcd0cf 100644 --- a/Procfile +++ b/Procfile @@ -1 +1,2 @@ -web: gunicorn gettingstarted.wsgi +release: python manage.py migrate +web: gunicorn gettingstarted.wsgi --log-file - From 028ce088d15c79f60259396aab758e6f0bd39cae Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Thu, 18 Oct 2018 17:15:29 -0500 Subject: [PATCH 045/143] realign with getting started guide --- Procfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Procfile b/Procfile index 2b2dcd0cf..47a27c07f 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1 @@ -release: python manage.py migrate web: gunicorn gettingstarted.wsgi --log-file - From a4da62ba6297e81d223a2f7e3f211f343022f0f0 Mon Sep 17 00:00:00 2001 From: Casey Faist Date: Wed, 10 Apr 2019 15:50:08 -0700 Subject: [PATCH 046/143] bump version --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index b16fb5e0e..6f651a3b1 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.7.0 \ No newline at end of file +python-3.7.3 From e1e95707fa2adbd0e52d7deb3f0d81a06a79baf9 Mon Sep 17 00:00:00 2001 From: Jon Mountjoy Date: Thu, 5 Dec 2019 11:43:42 +0000 Subject: [PATCH 047/143] Fix for static --- hello/templates/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hello/templates/index.html b/hello/templates/index.html index 8af29028b..d2912bf0e 100644 --- a/hello/templates/index.html +++ b/hello/templates/index.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% load staticfiles %} +{% load static %} {% block content %} From 41c3807ce309e2fdfe2fc2b28422a614e018e420 Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Sat, 18 Apr 2020 08:01:51 -0500 Subject: [PATCH 048/143] Upgrade to python 3.7.6 --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 6f651a3b1..6919bf9ed 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.7.3 +python-3.7.6 From 1f8fa8c0f2eb90d3cb97d09e489d27a34ae4c0a8 Mon Sep 17 00:00:00 2001 From: Nate <37554478+servusDei2018@users.noreply.github.com> Date: Mon, 3 Aug 2020 15:17:35 -0400 Subject: [PATCH 049/143] Update to Python 3.7.8 (#104) --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 6919bf9ed..32a8d83a0 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.7.6 +python-3.7.8 From 3109f8bed0e9fe0b0ad50097ee227485d5475cb9 Mon Sep 17 00:00:00 2001 From: schneems Date: Thu, 3 Sep 2020 14:20:36 -0500 Subject: [PATCH 050/143] Master => main --- README.md | 2 +- hello/templates/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8cbdb7f82..9969eac2f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Your app should now be running on [localhost:5000](http://localhost:5000/). ```sh $ heroku create -$ git push heroku master +$ git push heroku main $ heroku run python manage.py migrate $ heroku open diff --git a/hello/templates/index.html b/hello/templates/index.html index d2912bf0e..499baf77a 100644 --- a/hello/templates/index.html +++ b/hello/templates/index.html @@ -25,7 +25,7 @@

How this sample app work
  • This app was deployed to Heroku, either using Git or by using Heroku Button on the repository.
  • -
  • When Heroku received the source code, it fetched all the dependencies in the Pipfile, creating a deployable slug.
  • +
  • When Heroku received the source code, it fetched all the dependencies in the Pipfile, creating a deployable slug.
  • The platform then spins up a dyno, a lightweight container that provides an isolated environment in which the slug can be mounted and executed.
  • You can scale your app, manage it, and deploy over 150 add-on services, from the Dashboard or CLI.
From eef6cd4d5ecd17f5ae4b4baac184e08cc4e10ab7 Mon Sep 17 00:00:00 2001 From: kuaima Date: Thu, 18 Mar 2021 21:36:24 +0800 Subject: [PATCH 051/143] Update Python to 3.9.2 (#115) --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 32a8d83a0..30a1be66f 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.7.8 +python-3.9.2 From 0571b35efd81547e0b3cdff61de06415577cabf5 Mon Sep 17 00:00:00 2001 From: Eric Chen Date: Thu, 18 Mar 2021 06:51:22 -0700 Subject: [PATCH 052/143] Change 'staticfiles' to 'static' to support Django 3.0 (#95) --- hello/templates/db.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hello/templates/db.html b/hello/templates/db.html index e0e03d4c6..2d3a390ee 100644 --- a/hello/templates/db.html +++ b/hello/templates/db.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% load staticfiles %} +{% load static %} {% block content %}
@@ -18,4 +18,4 @@

Page View Report

-{% endblock %} \ No newline at end of file +{% endblock %} From 0f5c84379cba71adba58cdd731690dff1e0719c4 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 18 Mar 2021 14:03:33 +0000 Subject: [PATCH 053/143] README: Update required Python version to 3.9 (#123) Since the project was upgraded to 3.9 in #115. Also fixes the redirect in the installing Python guide link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9969eac2f..fe8b78b67 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This application supports the [Getting Started with Python on Heroku](https://de ## Running Locally -Make sure you have Python 3.7 [installed locally](http://install.python-guide.org). To push to Heroku, you'll need to install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli), as well as [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). +Make sure you have Python 3.9 [installed locally](https://docs.python-guide.org/starting/installation/). To push to Heroku, you'll need to install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli), as well as [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). ```sh $ git clone https://github.com/heroku/python-getting-started.git From 493f4045e970c4163a94b1fb75784c70e9c3124a Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 18 Mar 2021 14:38:48 +0000 Subject: [PATCH 054/143] Update obsolete reference to Pipfile (#124) Leftover from #64. --- hello/templates/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hello/templates/index.html b/hello/templates/index.html index 499baf77a..55951ccc2 100644 --- a/hello/templates/index.html +++ b/hello/templates/index.html @@ -25,7 +25,7 @@

How this sample app work
  • This app was deployed to Heroku, either using Git or by using Heroku Button on the repository.
  • -
  • When Heroku received the source code, it fetched all the dependencies in the Pipfile, creating a deployable slug.
  • +
  • When Heroku received the source code, it fetched all the dependencies in requirements.txt, creating a deployable slug.
  • The platform then spins up a dyno, a lightweight container that provides an isolated environment in which the slug can be mounted and executed.
  • You can scale your app, manage it, and deploy over 150 add-on services, from the Dashboard or CLI.
From cb7df096252bb7cc0bf17ae881a7509ecbc2cf5a Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 18 Mar 2021 15:33:11 +0000 Subject: [PATCH 055/143] Remove redundant `--log-file` gunicorn flag (#125) The gunicorn command line option `--log-file -` was renamed to `--error-logfile -` in gunicorn v0.13.0 in 2011: https://github.com/benoitc/gunicorn/commit/66f7271c5f67bedc576382a4384604298e6180a0 In addition, in gunicorn v19.2 (released 2015-01-30), `--error-logfile` defaults to `-` - so the option can be omitted entirely: http://docs.gunicorn.org/en/latest/settings.html#errorlog --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 47a27c07f..b6f89307b 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: gunicorn gettingstarted.wsgi --log-file - +web: gunicorn gettingstarted.wsgi From aa88d1946686c8994b59048d4379d5e495606b50 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 6 Apr 2021 13:54:35 +0100 Subject: [PATCH 056/143] Update Python to 3.9.4 (#128) https://www.python.org/downloads/release/python-394/ Closes GUS-W-9102388. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 30a1be66f..87665291b 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.9.2 +python-3.9.4 From e8ecbc00f6f2e99ef34157bcf6bfbabf9720756d Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 3 May 2021 20:50:20 +0100 Subject: [PATCH 057/143] Update Python to 3.9.5 (#131) https://www.python.org/downloads/release/python-395/ Closes GUS-W-9219520. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 87665291b..e19f0bb0e 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.9.4 +python-3.9.5 From 66d69d759dac01b473cb674dc30bcc5dc947a50f Mon Sep 17 00:00:00 2001 From: Arthur Lutz Date: Tue, 6 Jul 2021 18:53:33 +0200 Subject: [PATCH 058/143] Update Python to 3.9.6 (#138) https://www.python.org/downloads/release/python-396/ --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index e19f0bb0e..9bff0e00f 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.9.5 +python-3.9.6 From e9ee943a4f792e0c9ce3994e7c72df0587b90b98 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 30 Aug 2021 23:53:41 +0100 Subject: [PATCH 059/143] Update to Python 3.9.7 (#139) https://www.python.org/downloads/release/python-397/ --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 9bff0e00f..2153d1e15 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.9.6 +python-3.9.7 From 1f4c6160e60dba874957da5b73c37f4572d294f7 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 29 Oct 2021 14:16:55 +0100 Subject: [PATCH 060/143] Update to Python 3.10.0 (#143) Release announcement: https://www.python.org/downloads/release/python-3100/ https://blog.python.org/2021/10/python-3100-is-available.html More detailed "What's new": https://docs.python.org/3.10/whatsnew/3.10.html GUS-W-10103526. --- README.md | 2 +- runtime.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe8b78b67..1e7a9ec2e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This application supports the [Getting Started with Python on Heroku](https://de ## Running Locally -Make sure you have Python 3.9 [installed locally](https://docs.python-guide.org/starting/installation/). To push to Heroku, you'll need to install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli), as well as [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). +Make sure you have Python 3.10 [installed locally](https://docs.python-guide.org/starting/installation/). To push to Heroku, you'll need to install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli), as well as [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). ```sh $ git clone https://github.com/heroku/python-getting-started.git diff --git a/runtime.txt b/runtime.txt index 2153d1e15..fadb07024 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.9.7 +python-3.10.0 From ac80f787d55b09c2c768a57b8eeb395a19101408 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 7 Dec 2021 00:23:54 +0000 Subject: [PATCH 061/143] Update to Python 3.10.1 (#146) https://www.python.org/downloads/release/python-3101/ GUS-W-10273300. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index fadb07024..2b301d546 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.0 +python-3.10.1 From 0d34857e5343f23b6d8dfcb6d85fb16200a911c0 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Sat, 15 Jan 2022 12:02:37 +0000 Subject: [PATCH 062/143] Update to Python 3.10.2 (#148) https://www.python.org/downloads/release/python-3102/ GUS-W-10440845. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 2b301d546..250d1e3df 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.1 +python-3.10.2 From 9659528f0d345b64a408d7ddced45b28947799b6 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 4 Feb 2022 15:34:57 +0000 Subject: [PATCH 063/143] Simplify the README (#152) Previously it duplicated parts of the getting started guide, but was missing steps and also didn't have instructions for all platforms (eg Windows). Rather than trying to have brief instructions here (which somewhat miss the point of having a tutorial) that are at risk of getting out of sync with the guide, it makes more sense to only link to the guide. --- README.md | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 1e7a9ec2e..3d7369d95 100644 --- a/README.md +++ b/README.md @@ -2,44 +2,12 @@ A barebones Django app, which can easily be deployed to Heroku. -This application supports the [Getting Started with Python on Heroku](https://devcenter.heroku.com/articles/getting-started-with-python) article - check it out. +This application supports the [Getting Started with Python on Heroku](https://devcenter.heroku.com/articles/getting-started-with-python) article - check it out for instructions on how to deploy this app to Heroku and also run it locally. -## Running Locally - -Make sure you have Python 3.10 [installed locally](https://docs.python-guide.org/starting/installation/). To push to Heroku, you'll need to install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli), as well as [Postgres](https://devcenter.heroku.com/articles/heroku-postgresql#local-setup). - -```sh -$ git clone https://github.com/heroku/python-getting-started.git -$ cd python-getting-started - -$ python3 -m venv getting-started -$ pip install -r requirements.txt - -$ createdb python_getting_started - -$ python manage.py migrate -$ python manage.py collectstatic - -$ heroku local -``` - -Your app should now be running on [localhost:5000](http://localhost:5000/). - -## Deploying to Heroku - -```sh -$ heroku create -$ git push heroku main - -$ heroku run python manage.py migrate -$ heroku open -``` -or +Alternatively, you can deploy it using this Heroku Button: [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) -## Documentation - For more information about using Python on Heroku, see these Dev Center articles: - [Python on Heroku](https://devcenter.heroku.com/categories/python) From d1074b2e2958a2c9c55b029e268638e2c6e10615 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 16 Mar 2022 22:45:17 +0000 Subject: [PATCH 064/143] Update to Python 3.10.3 (#156) https://blog.python.org/2022/03/python-3103-3911-3813-and-3713-are-now.html https://www.python.org/downloads/release/python-3103/ GUS-W-10858725. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 250d1e3df..30e81e313 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.2 +python-3.10.3 From 18e313cf54e2bc593311d7c4f6f7a74eb6b0a41f Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 24 Mar 2022 13:47:10 +0000 Subject: [PATCH 065/143] Update to Python 3.10.4 (#157) https://blog.python.org/2022/03/python-3104-and-3912-are-now-available.html https://devcenter.heroku.com/changelog-items/2373 GUS-W-10894050. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 30e81e313..73e24dc79 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.3 +python-3.10.4 From 26d9f9362f772bfe2f28092781388f193e68f861 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 7 Jun 2022 12:14:50 +0100 Subject: [PATCH 066/143] Update to Python 3.10.5 (#163) https://blog.python.org/2022/06/python-3105-is-available_6.html https://devcenter.heroku.com/changelog-items/2424 GUS-W-11258686. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 73e24dc79..a5da7cc4d 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.4 +python-3.10.5 From 2ee0f494a613e2b8d0afded2e5191d9161de2809 Mon Sep 17 00:00:00 2001 From: Prateek Sane <61072843+PrateekSane@users.noreply.github.com> Date: Tue, 28 Jun 2022 10:25:37 -0700 Subject: [PATCH 067/143] added version bounds for django (#166) * added version bounds for django * less restrictive bound * upper bound less than 5.0 rather than less or eq Co-authored-by: Prateek Sane --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4af6a3765..2beedcf00 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -django +django>=4.0, <5.0 gunicorn django-heroku \ No newline at end of file From 14230b2be293b5a94deb8c7caeb8c7727adb9ec0 Mon Sep 17 00:00:00 2001 From: Prateek Sane <61072843+PrateekSane@users.noreply.github.com> Date: Thu, 28 Jul 2022 02:12:56 -0700 Subject: [PATCH 068/143] Migrate away from the deprecated `django-heroku` package (#167) The `django-heroku` package is deprecated/sunset since it's no longer the preferred way for configuring Django on Heroku. As such, the config from `django-heroku` has now been inlined into this project and simplified. GUS-W-8012597. --- gettingstarted/settings.py | 83 +++++++++++++++++++++++++++++--------- requirements.txt | 8 ++-- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 9ea552a0c..b00430d2e 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -1,34 +1,46 @@ """ Django settings for gettingstarted project. -Generated by 'django-admin startproject' using Django 2.0. +Generated by 'django-admin startproject' using Django 4.0. For more information on this file, see -https://docs.djangoproject.com/en/2.0/topics/settings/ +https://docs.djangoproject.com/en/4.0/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/2.0/ref/settings/ +https://docs.djangoproject.com/en/4.0/topics/settings/ """ +import dj_database_url import os -import django_heroku +from django.test.runner import DiscoverRunner +from pathlib import Path # Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +BASE_DIR = Path(__file__).resolve().parent.parent +IS_HEROKU = "DYNO" in os.environ + # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = "CHANGE_ME!!!! (P.S. the SECRET_KEY environment variable will be used, if set, instead)." -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +if 'SECRET_KEY' in os.environ: + SECRET_KEY = os.environ["SECRET_KEY"] -ALLOWED_HOSTS = [] +# Generally avoid wildcards(*). However since Heroku router provides hostname validation it is ok +if IS_HEROKU: + ALLOWED_HOSTS = ["*"] +else: + ALLOWED_HOSTS = [] + +# SECURITY WARNING: don't run with debug turned on in production! +if not IS_HEROKU: + DEBUG = True # Application definition @@ -44,6 +56,7 @@ MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", @@ -74,17 +87,29 @@ # Database -# https://docs.djangoproject.com/en/2.0/ref/settings/#databases +# https://docs.djangoproject.com/en/4.0/ref/settings/#databases + +MAX_CONN_AGE = 600 DATABASES = { "default": { - "ENGINE" : "django.db.backends.sqlite3", + "ENGINE": "django.db.backends.sqlite3", "NAME": os.path.join(BASE_DIR, "db.sqlite3") } } +if "DATABASE_URL" in os.environ: + # Configure Django for DATABASE_URL environment variable. + DATABASES["default"] = dj_database_url.config( + conn_max_age=MAX_CONN_AGE, ssl_require=True) + + # Enable test database if found in CI environment. + if "CI" in os.environ: + DATABASES["default"]["TEST"] = DATABASES["default"] + + # Password validation -# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -97,7 +122,7 @@ # Internationalization -# https://docs.djangoproject.com/en/2.0/topics/i18n/ +# https://docs.djangoproject.com/en/4.0/topics/i18n/ LANGUAGE_CODE = "en-us" @@ -105,15 +130,35 @@ USE_I18N = True -USE_L10N = True - USE_TZ = True # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/2.0/howto/static-files/ +# https://docs.djangoproject.com/en/4.0/howto/static-files/ + +STATIC_ROOT = BASE_DIR / "staticfiles" +STATIC_URL = "static/" + +# Enable WhiteNoise's GZip compression of static assets. +STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" + + +# Test Runner Config +class HerokuDiscoverRunner(DiscoverRunner): + """Test Runner for Heroku CI, which provides a database for you. + This requires you to set the TEST database (done for you by settings().)""" + + def setup_databases(self, **kwargs): + self.keepdb = True + return super(HerokuDiscoverRunner, self).setup_databases(**kwargs) + + +# Use HerokuDiscoverRunner on Heroku CI +if "CI" in os.environ: + TEST_RUNNER = "gettingstarted.settings.HerokuDiscoverRunner" + -STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') -STATIC_URL = "/static/" +# Default primary key field type +# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field -django_heroku.settings(locals()) +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/requirements.txt b/requirements.txt index 2beedcf00..b8920271d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ -django>=4.0, <5.0 -gunicorn -django-heroku \ No newline at end of file +django>=4.0,<5.0 +gunicorn>=20.0,<21.0 +dj-database-url>=0.5,<0.6 +whitenoise>=6.0,<7.0 +psycopg2>=2.0,<3.0 From f469539ac779da74402182293e2d63e430fd6c7a Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 2 Aug 2022 12:59:01 +0100 Subject: [PATCH 069/143] Update to Python 3.10.6 (#171) https://blog.python.org/2022/08/python-3106-is-available.html https://www.python.org/downloads/release/python-3106/ https://docs.python.org/release/3.10.6/whatsnew/changelog.html#python-3-10-6-final GUS-W-11532135. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index a5da7cc4d..7a33c420a 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.5 +python-3.10.6 From 6af9b3ceec4df09355126e7e7ab65359d329c7fd Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 3 Aug 2022 10:36:14 +0100 Subject: [PATCH 070/143] Update `dj-database-url` to 1.x (#172) `dj-database-url` v1.0.0 was just released: https://github.com/jazzband/dj-database-url/releases/tag/v1.0.0 The only breaking change is dropping of Python 2.7 support, which doesn't affect this project. Changes: https://github.com/jazzband/dj-database-url/blob/master/CHANGELOG.md#v100-2022-18-06 https://github.com/jazzband/dj-database-url/compare/v0.5.0...v1.0.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b8920271d..6ba2d1396 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ django>=4.0,<5.0 gunicorn>=20.0,<21.0 -dj-database-url>=0.5,<0.6 +dj-database-url>=1.0,<2.0 whitenoise>=6.0,<7.0 psycopg2>=2.0,<3.0 From dc9787a6e3803207a3119eac0857411d49597a00 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 6 Sep 2022 14:54:07 +0100 Subject: [PATCH 071/143] Update to Python 3.10.7 (#173) https://www.python.org/downloads/release/python-3107/ https://docs.python.org/release/3.10.7/whatsnew/changelog.html#python-3-10-7-final GUS-W-11700841. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 7a33c420a..119ff1023 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.6 +python-3.10.7 From 0a6a79dfe9deb2065f1c51f740288ebbbec23a3b Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 21 Sep 2022 18:06:38 +0100 Subject: [PATCH 072/143] Regenerate initial migrations (#177) To prevent this warning when running `./manage.py migrate`: ``` Your models in app(s): 'hello' have changes that are not yet reflected in a migration, and so won't be applied. Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them. ``` The changes were generated by deleting the file, then running: `./manage.py makemigrations` GUS-W-11792497. --- hello/migrations/0001_initial.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/hello/migrations/0001_initial.py b/hello/migrations/0001_initial.py index 99c4a82a5..3a6fd11d9 100644 --- a/hello/migrations/0001_initial.py +++ b/hello/migrations/0001_initial.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.1 on 2016-01-27 21:54 -from __future__ import unicode_literals +# Generated by Django 4.1.1 on 2022-09-21 16:58 from django.db import migrations, models @@ -9,15 +7,27 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Greeting', + name="Greeting", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('when', models.DateTimeField(auto_now_add=True, verbose_name=b'date created')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "when", + models.DateTimeField( + auto_now_add=True, verbose_name="date created" + ), + ), ], ), ] From 907e3dc44fc01313fd14cb6de1cf29aa50bb60e0 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 12 Oct 2022 09:13:27 +0100 Subject: [PATCH 073/143] Update to Python 3.10.8 (#179) https://www.python.org/downloads/release/python-3108/ https://blog.python.org/2022/10/python-versions-3108-3915-3815-3715-now.html GUS-W-11892706. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 119ff1023..69b0ccfc8 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.7 +python-3.10.8 From d9837b4ddbeee4c9a0cb43605153782db3ba68e9 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 25 Oct 2022 09:21:31 +0100 Subject: [PATCH 074/143] Update to Python 3.11.0 (#181) https://blog.python.org/2022/10/python-3110-is-now-available.html GUS-W-11952410. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 69b0ccfc8..335156c09 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.8 +python-3.11.0 From 4666497b43eef04856f40d5d51a336ffea166be7 Mon Sep 17 00:00:00 2001 From: Jonathan McAllister Date: Mon, 28 Nov 2022 10:34:26 -0800 Subject: [PATCH 075/143] Update README for ending of free plans (#184) * readme changes for efp. do not merge until 11/28 * recommend deleting the app vs scaling to 0 upon completion Co-authored-by: Jonathan McAllister --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 3d7369d95..897f15e7f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,14 @@ A barebones Django app, which can easily be deployed to Heroku. +## Deploying to Heroku + +Using resources for this example app counts towards your usage. [Delete your app](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-apps-destroy) and [database](https://devcenter.heroku.com/articles/heroku-postgresql#removing-the-add-on) as soon as you are done experimenting to control costs. + +By default, apps use Eco dynos if you are subscribed to Eco. Otherwise, it defaults to Basic dynos. The Eco dynos plan is shared across all Eco dynos in your account and is recommended if you plan on deploying many small apps to Heroku. Learn more about our low-cost plans [here](https://blog.heroku.com/new-low-cost-plans). + +Eligible students can apply for platform credits through our new [Heroku for GitHub Students program](https://blog.heroku.com/github-student-developer-program). + This application supports the [Getting Started with Python on Heroku](https://devcenter.heroku.com/articles/getting-started-with-python) article - check it out for instructions on how to deploy this app to Heroku and also run it locally. Alternatively, you can deploy it using this Heroku Button: From 270a57be7f1430923681803f9e430514ead6499e Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 7 Dec 2022 00:43:03 +0000 Subject: [PATCH 076/143] Update to Python 3.11.1 (#185) https://blog.python.org/2022/12/python-3111-3109-3916-3816-3716-and.html GUS-W-12177927. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 335156c09..4b44813f0 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.0 +python-3.11.1 From f15b44316cd0078e72bfb5057f7a49ef7b38586c Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 8 Feb 2023 13:12:09 +0000 Subject: [PATCH 077/143] Update to Python 3.11.2 (#186) https://www.python.org/downloads/release/python-3112/ GUS-W-12512190. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 4b44813f0..04d03e383 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.1 +python-3.11.2 From 7d2f6a12b1cabc1551e2d0d7ad46844fd9091c56 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 6 Apr 2023 09:25:52 +0100 Subject: [PATCH 078/143] Update to Python 3.11.3 (#187) https://www.python.org/downloads/release/python-3113/ GUS-W-12512198. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 04d03e383..afe12ad1b 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.2 +python-3.11.3 From 02eb1411331cd23c7e692887cf317caba5363557 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 13:04:43 +0100 Subject: [PATCH 079/143] Format the codebase using Black (#188) https://github.com/psf/black (This isn't being enforced in CI, since this project is a template, so we can't add a bunch of opinionated CI checks etc) GUS-W-13312373. --- gettingstarted/settings.py | 28 ++++++++++++++++++---------- hello/migrations/0001_initial.py | 1 - hello/models.py | 2 ++ hello/views.py | 3 ++- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index b00430d2e..57212c579 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -28,7 +28,7 @@ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = "CHANGE_ME!!!! (P.S. the SECRET_KEY environment variable will be used, if set, instead)." -if 'SECRET_KEY' in os.environ: +if "SECRET_KEY" in os.environ: SECRET_KEY = os.environ["SECRET_KEY"] @@ -78,9 +78,9 @@ "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", - ] + ], }, - } + }, ] WSGI_APPLICATION = "gettingstarted.wsgi.application" @@ -94,14 +94,16 @@ DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", - "NAME": os.path.join(BASE_DIR, "db.sqlite3") + "NAME": os.path.join(BASE_DIR, "db.sqlite3"), } } if "DATABASE_URL" in os.environ: # Configure Django for DATABASE_URL environment variable. DATABASES["default"] = dj_database_url.config( - conn_max_age=MAX_CONN_AGE, ssl_require=True) + conn_max_age=MAX_CONN_AGE, + ssl_require=True, + ) # Enable test database if found in CI environment. if "CI" in os.environ: @@ -113,11 +115,17 @@ AUTH_PASSWORD_VALIDATORS = [ { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, - {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, - {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, - {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, ] @@ -161,4 +169,4 @@ def setup_databases(self, **kwargs): # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/hello/migrations/0001_initial.py b/hello/migrations/0001_initial.py index 3a6fd11d9..7099df50f 100644 --- a/hello/migrations/0001_initial.py +++ b/hello/migrations/0001_initial.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - initial = True dependencies = [] diff --git a/hello/models.py b/hello/models.py index 8229092ef..974d64f7e 100644 --- a/hello/models.py +++ b/hello/models.py @@ -1,5 +1,7 @@ from django.db import models # Create your models here. + + class Greeting(models.Model): when = models.DateTimeField("date created", auto_now_add=True) diff --git a/hello/views.py b/hello/views.py index c2480724b..99dd346ae 100644 --- a/hello/views.py +++ b/hello/views.py @@ -4,13 +4,14 @@ from .models import Greeting # Create your views here. + + def index(request): # return HttpResponse('Hello from Python!') return render(request, "index.html") def db(request): - greeting = Greeting() greeting.save() From ee887769561026ae56d031aac04bf3455f9eec30 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 13:11:18 +0100 Subject: [PATCH 080/143] Clean up `.gitignore` (#189) * Add `.DS_Store` (macOS metadata files) * Add `.venv/` since it's a commonly used virtual environment directory name (the existing `venv/` name is still ignored too) * Switch from `*.pyc` to `__pycache__/` (the former is the Python 2 style) * The redundant `getting-started/*` entry has been removed (I presume this might have been a leftover from the "install local package as egg" days GUS-W-13312373. --- .gitignore | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 4875ad398..2f694d7b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ -venv -*.pyc -staticfiles -.env +# Python files +__pycache__/ +.venv/ +venv/ + +# Django files +staticfiles/ db.sqlite3 -getting-started/* \ No newline at end of file + +# macOS files +.DS_Store From b4f9e3f641836c6060921dacef2c999b382c60ea Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 14:52:45 +0100 Subject: [PATCH 081/143] Remove dead code (#190) GUS-W-13312373. --- gettingstarted/static/humans.txt | 0 gettingstarted/urls.py | 3 +-- hello/tests.py | 2 +- hello/views.py | 2 -- 4 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 gettingstarted/static/humans.txt diff --git a/gettingstarted/static/humans.txt b/gettingstarted/static/humans.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index 13b759582..b322c9e13 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -1,6 +1,5 @@ -from django.urls import path, include - from django.contrib import admin +from django.urls import path admin.autodiscover() diff --git a/hello/tests.py b/hello/tests.py index 9b06366a5..14b1b7446 100644 --- a/hello/tests.py +++ b/hello/tests.py @@ -1,4 +1,4 @@ -from django.contrib.auth.models import AnonymousUser, User +from django.contrib.auth.models import AnonymousUser from django.test import TestCase, RequestFactory from .views import index diff --git a/hello/views.py b/hello/views.py index 99dd346ae..79fd8b131 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,5 +1,4 @@ from django.shortcuts import render -from django.http import HttpResponse from .models import Greeting @@ -7,7 +6,6 @@ def index(request): - # return HttpResponse('Hello from Python!') return render(request, "index.html") From 37f270a4fd77045f96900100b7557a3d10ce9c8d Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 15:00:10 +0100 Subject: [PATCH 082/143] Improve example unit tests (#191) The example unit tests have been rewritten to actually test the app, and so they no longer use unnecessary setup boilerplate. --- hello/tests.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/hello/tests.py b/hello/tests.py index 14b1b7446..8134bff8b 100644 --- a/hello/tests.py +++ b/hello/tests.py @@ -1,19 +1,26 @@ -from django.contrib.auth.models import AnonymousUser -from django.test import TestCase, RequestFactory +from django.test import TestCase -from .views import index +# Create your tests here. -class SimpleTest(TestCase): - def setUp(self): - # Every test needs access to the request factory. - self.factory = RequestFactory() +# Note: The tests below rely upon static assets (for the rendered templates), so require that either: +# 1. The static assets have been processed - ie: `./manage.py collectstatic` has been run. +# 2. Or, the tests are run in debug mode (which means WhiteNoise will use auto-refresh mode), +# using: `./manage.py test --debug-mode` +class ExampleTest(TestCase): + def test_index_page(self): + response = self.client.get("/") + self.assertContains( + response, "Getting Started with Python on Heroku", status_code=200 + ) - def test_details(self): - # Create an instance of a GET request. - request = self.factory.get("/") - request.user = AnonymousUser() + def test_db_page(self): + # Each time the page is requested, the number of recorded greetings increases. - # Test my_view() as if it were deployed at /customer/details - response = index(request) - self.assertEqual(response.status_code, 200) + first_response = self.client.get("/db/") + self.assertEqual(first_response.status_code, 200) + self.assertEqual(len(first_response.context["greetings"]), 1) + + second_response = self.client.get("/db/") + self.assertEqual(second_response.status_code, 200) + self.assertEqual(len(second_response.context["greetings"]), 2) From 17a18003970761e96eba1e9cf7a35767c8143fc3 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 15:03:54 +0100 Subject: [PATCH 083/143] Fix the Heroku Button URL (#192) The previous URL didn't specify an explicit template parameter, which means Dashboard has to rely upon the referrer, which is no longer passed on, meaning the Button had stopped working. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 897f15e7f..0e937f1b9 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This application supports the [Getting Started with Python on Heroku](https://de Alternatively, you can deploy it using this Heroku Button: -[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/heroku/python-getting-started) For more information about using Python on Heroku, see these Dev Center articles: From 317c8654fc841688a0af2e588bc770e5c523586b Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 15:50:50 +0100 Subject: [PATCH 084/143] Port changes from the upstream `startproject` template (#194) This guide is intentionally closely based around the template project generated by Django's `startproject` and `startapp` commands. This ports changes from the upstream template that were made in the last few versions of Django. The upstream template content was generated using: ``` django-admin startproject gettingstarted cd gettingstarted ./manage.py startapp hello ``` --- gettingstarted/asgi.py | 16 ++++++++++++++++ gettingstarted/settings.py | 29 ++++++++++++++--------------- gettingstarted/urls.py | 26 ++++++++++++++++---------- gettingstarted/wsgi.py | 6 +++--- hello/apps.py | 6 ++++++ hello/migrations/0001_initial.py | 2 +- manage.py | 18 +++++++++++++++--- 7 files changed, 71 insertions(+), 32 deletions(-) create mode 100644 gettingstarted/asgi.py create mode 100644 hello/apps.py diff --git a/gettingstarted/asgi.py b/gettingstarted/asgi.py new file mode 100644 index 000000000..7390dd016 --- /dev/null +++ b/gettingstarted/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for gettingstarted project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gettingstarted.settings") + +application = get_asgi_application() diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 57212c579..f66926827 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -1,13 +1,13 @@ """ Django settings for gettingstarted project. -Generated by 'django-admin startproject' using Django 4.0. +Generated by 'django-admin startproject' using Django 4.2.1. For more information on this file, see -https://docs.djangoproject.com/en/4.0/topics/settings/ +https://docs.djangoproject.com/en/4.2/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.0/topics/settings/ +https://docs.djangoproject.com/en/4.2/ref/settings/ """ import dj_database_url @@ -15,15 +15,14 @@ from django.test.runner import DiscoverRunner from pathlib import Path - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +# Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent IS_HEROKU = "DYNO" in os.environ # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = "CHANGE_ME!!!! (P.S. the SECRET_KEY environment variable will be used, if set, instead)." @@ -31,6 +30,9 @@ if "SECRET_KEY" in os.environ: SECRET_KEY = os.environ["SECRET_KEY"] +# SECURITY WARNING: don't run with debug turned on in production! +if not IS_HEROKU: + DEBUG = True # Generally avoid wildcards(*). However since Heroku router provides hostname validation it is ok if IS_HEROKU: @@ -38,9 +40,6 @@ else: ALLOWED_HOSTS = [] -# SECURITY WARNING: don't run with debug turned on in production! -if not IS_HEROKU: - DEBUG = True # Application definition @@ -87,14 +86,14 @@ # Database -# https://docs.djangoproject.com/en/4.0/ref/settings/#databases +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases MAX_CONN_AGE = 600 DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", - "NAME": os.path.join(BASE_DIR, "db.sqlite3"), + "NAME": BASE_DIR / "db.sqlite3", } } @@ -111,7 +110,7 @@ # Password validation -# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -130,7 +129,7 @@ # Internationalization -# https://docs.djangoproject.com/en/4.0/topics/i18n/ +# https://docs.djangoproject.com/en/4.2/topics/i18n/ LANGUAGE_CODE = "en-us" @@ -142,7 +141,7 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/4.0/howto/static-files/ +# https://docs.djangoproject.com/en/4.2/howto/static-files/ STATIC_ROOT = BASE_DIR / "staticfiles" STATIC_URL = "static/" @@ -167,6 +166,6 @@ def setup_databases(self, **kwargs): # Default primary key field type -# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index b322c9e13..66e598b4d 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -1,18 +1,24 @@ +""" +URL configuration for gettingstarted project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" from django.contrib import admin from django.urls import path -admin.autodiscover() - import hello.views -# To add a new path, first import the app: -# import blog -# -# Then add the new path: -# path('blog/', blog.urls, name="blog") -# -# Learn more here: https://docs.djangoproject.com/en/2.1/topics/http/urls/ - urlpatterns = [ path("", hello.views.index, name="index"), path("db/", hello.views.db, name="db"), diff --git a/gettingstarted/wsgi.py b/gettingstarted/wsgi.py index 3c528d7ce..4508266fb 100644 --- a/gettingstarted/wsgi.py +++ b/gettingstarted/wsgi.py @@ -4,13 +4,13 @@ It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ """ import os -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gettingstarted.settings") - from django.core.wsgi import get_wsgi_application +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gettingstarted.settings") + application = get_wsgi_application() diff --git a/hello/apps.py b/hello/apps.py new file mode 100644 index 000000000..6b541fb46 --- /dev/null +++ b/hello/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class HelloConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "hello" diff --git a/hello/migrations/0001_initial.py b/hello/migrations/0001_initial.py index 7099df50f..4e116477b 100644 --- a/hello/migrations/0001_initial.py +++ b/hello/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1.1 on 2022-09-21 16:58 +# Generated by Django 4.2.1 on 2023-05-18 12:17 from django.db import migrations, models diff --git a/manage.py b/manage.py index eb3ab8af5..f10541cac 100755 --- a/manage.py +++ b/manage.py @@ -1,10 +1,22 @@ #!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" import os import sys -if __name__ == "__main__": + +def main(): + """Run administrative tasks.""" os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gettingstarted.settings") + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) - from django.core.management import execute_from_command_line - execute_from_command_line(sys.argv) +if __name__ == "__main__": + main() From 9aae1a5f3cdf13c968f7fec3acecdc31cbe15246 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 15:56:38 +0100 Subject: [PATCH 085/143] Enable Dependabot (#195) So that it can bump the major version ranges in `requirements.txt`. See: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..55dbe8564 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "monthly" From 27c9f9e5ac1debc8a608cc66b28462c2b4653be1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 May 2023 15:06:51 +0000 Subject: [PATCH 086/143] Update dj-database-url requirement from <2.0,>=1.0 to >=2.0,<3.0 (#196) * Update dj-database-url requirement from <2.0,>=1.0 to >=1.0,<3.0 Updates the requirements on [dj-database-url](https://github.com/jazzband/dj-database-url) to permit the latest version. - [Release notes](https://github.com/jazzband/dj-database-url/releases) - [Changelog](https://github.com/jazzband/dj-database-url/blob/master/CHANGELOG.md) - [Commits](https://github.com/jazzband/dj-database-url/compare/v1.0.0...v2.0.0) --- updated-dependencies: - dependency-name: dj-database-url dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Raise minimum dj-database-url version to 2.0 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6ba2d1396..20ea5babd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ django>=4.0,<5.0 gunicorn>=20.0,<21.0 -dj-database-url>=1.0,<2.0 +dj-database-url>=2.0,<3.0 whitenoise>=6.0,<7.0 psycopg2>=2.0,<3.0 From c0f61986df099360495a9397b4bc3f1e92ba9990 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 16:19:45 +0100 Subject: [PATCH 087/143] Use `--debug-mode` for tests instead of running collectstatic (#197) Running the tests in debug mode means WhiteNoise uses its development mode file finder, which means collectstatic doesn't need to have been run first. In CI either approach is equally valid, however, locally it's very easy to forget to run collectstatic, so we use the `--debug-mode` approach in `app.json` so users know about this trick when reading the codebase. --- app.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app.json b/app.json index 8721c4994..07573dad9 100644 --- a/app.json +++ b/app.json @@ -3,8 +3,8 @@ "description": "A barebones Python app, which can easily be deployed to Heroku.", "image": "heroku/python", "repository": "https://github.com/heroku/python-getting-started", - "keywords": ["python", "django" ], - "addons": [ "heroku-postgresql" ], + "keywords": ["python", "django"], + "addons": ["heroku-postgresql"], "env": { "SECRET_KEY": { "description": "The secret key for the Django application.", @@ -14,8 +14,7 @@ "environments": { "test": { "scripts": { - "test-setup": "python manage.py collectstatic --noinput", - "test": "python manage.py test" + "test": "./manage.py test --debug-mode" } } } From 4465fc216b8dea9b7f37c1e282969764fabc0860 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 16:24:36 +0100 Subject: [PATCH 088/143] Disable Django admin by default (#198) The Django admin panel feature has been commented out, to improve security, and to reduce the number of static files that have to be processed during collectstatic. (Given that many people won't use the feature, and it requires additional user setup before it can be used anyway.) --- gettingstarted/settings.py | 4 +++- gettingstarted/urls.py | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index f66926827..f16648796 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -44,7 +44,9 @@ # Application definition INSTALLED_APPS = [ - "django.contrib.admin", + # Uncomment this and the entry in `urls.py` if you wish to use the Django admin feature: + # https://docs.djangoproject.com/en/4.2/ref/contrib/admin/ + # "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index 66e598b4d..7b1971804 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -14,7 +14,7 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ -from django.contrib import admin +# from django.contrib import admin from django.urls import path import hello.views @@ -22,5 +22,7 @@ urlpatterns = [ path("", hello.views.index, name="index"), path("db/", hello.views.db, name="db"), - path("admin/", admin.site.urls), + # Uncomment this and the entry in `INSTALLED_APPS` if you wish to use the Django admin feature: + # https://docs.djangoproject.com/en/4.2/ref/contrib/admin/ + # path("admin/", admin.site.urls), ] From 5ec6d70f92a1658627a453e44ba2b44350b11500 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 16:58:06 +0100 Subject: [PATCH 089/143] Improve WhiteNoise configuration (#199) * Switch from the deprecated `STATICFILES_STORAGE` Django config option to `STORAGES` * Add `whitenoise.runserver_nostatic` to `INSTALLED_APPS` so that WhiteNoise's runserver implementation is used instead of Django's default implementation, for improved dev-prod parity * Enable `WHITENOISE_KEEP_ONLY_HASHED_FILES`, which means the original (un-hashed filename) copy of static assets are no longer unnecessarily stored in the slug. (This does mean all Django templates must use the `static` processor for asset URLs, but all of the templates in this guide do that already.) * Use the `brotli` WhiteNoise package extra, so that the Brotli package ends up being installed, so that static assets can also be served using the more efficient Brotli compression (for browsers that support it, which is all modern browsers), and not just GZip. See: https://whitenoise.readthedocs.io/en/latest/django.html --- gettingstarted/settings.py | 19 +++++++++++++++++-- requirements.txt | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index f16648796..2a2ca54a5 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -44,6 +44,8 @@ # Application definition INSTALLED_APPS = [ + # Use WhiteNoise's runserver implementation instead of the Django default, for dev-prod parity. + "whitenoise.runserver_nostatic", # Uncomment this and the entry in `urls.py` if you wish to use the Django admin feature: # https://docs.djangoproject.com/en/4.2/ref/contrib/admin/ # "django.contrib.admin", @@ -57,6 +59,10 @@ MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", + # Django doesn't support serving static assets in a production-ready way, so we use the + # excellent WhiteNoise package to do so instead. The WhiteNoise middleware must be listed + # after Django's `SecurityMiddleware` so that security redirects are still performed. + # See: https://whitenoise.readthedocs.io "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", @@ -148,8 +154,17 @@ STATIC_ROOT = BASE_DIR / "staticfiles" STATIC_URL = "static/" -# Enable WhiteNoise's GZip compression of static assets. -STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" +STORAGES = { + # Enable WhiteNoise's GZip and Brotli compression of static assets: + # https://whitenoise.readthedocs.io/en/latest/django.html#add-compression-and-caching-support + "staticfiles": { + "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", + }, +} + +# Don't store the original (un-hashed filename) version of static files, to reduce slug size: +# https://whitenoise.readthedocs.io/en/latest/django.html#WHITENOISE_KEEP_ONLY_HASHED_FILES +WHITENOISE_KEEP_ONLY_HASHED_FILES = True # Test Runner Config diff --git a/requirements.txt b/requirements.txt index 20ea5babd..77c9cba1c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ django>=4.0,<5.0 gunicorn>=20.0,<21.0 dj-database-url>=2.0,<3.0 -whitenoise>=6.0,<7.0 +whitenoise[brotli]>=6.0,<7.0 psycopg2>=2.0,<3.0 From 20b3df730e4a02e3786370dd8f5b1fb1ee567a12 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 17:08:18 +0100 Subject: [PATCH 090/143] Add a comment explaining the `.env` file (#200) See: https://devcenter.heroku.com/articles/heroku-local#set-up-your-local-environment-variables --- .env | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.env b/.env index 06f57c520..fbb3c134e 100644 --- a/.env +++ b/.env @@ -1 +1,6 @@ +# This file specifies the environment variables that will be set when using the +# `heroku local` command locally during development. It has no effect on apps +# running on Heroku - to set env vars for those, see: +# https://devcenter.heroku.com/articles/config-vars + TIMES=2 From ed1f1b8ff1d932f5d082080cdc882fa941ede8dd Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 17:18:53 +0100 Subject: [PATCH 091/143] Use a randomised Django secret key if one isn't set explicitly (#201) The Django secret key is no longer hardcoded to an example value, instead using a randomised value if the recommend env var is not set. The previous implementation could be insecure if users didn't set an explicit value, and also encouraged secrets being committed to source rather than the use of env vars. The name of the env var has also been renamed from `SECRET_KEY` to `DJANGO_SECRET_KEY`. --- app.json | 2 +- gettingstarted/settings.py | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/app.json b/app.json index 07573dad9..5ac160092 100644 --- a/app.json +++ b/app.json @@ -6,7 +6,7 @@ "keywords": ["python", "django"], "addons": ["heroku-postgresql"], "env": { - "SECRET_KEY": { + "DJANGO_SECRET_KEY": { "description": "The secret key for the Django application.", "generator": "secret" } diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 2a2ca54a5..f4d9eafe0 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -10,25 +10,35 @@ https://docs.djangoproject.com/en/4.2/ref/settings/ """ -import dj_database_url import os -from django.test.runner import DiscoverRunner +import secrets from pathlib import Path +import dj_database_url +from django.test.runner import DiscoverRunner + # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent IS_HEROKU = "DYNO" in os.environ -# Quick-start development settings - unsuitable for production +# Before using your Heroku app in production, make sure to review Django's deployment checklist: # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ +# Django requires a unique secret key for each Django app, that is used by several of its +# security features. To simplify initial setup (without hardcoding the secret in the source +# code) we set this to a random value every time the app starts. However, this will mean many +# Django features break whenever an app restarts (for example, sessions will be logged out). +# In your production Heroku apps you should set the `DJANGO_SECRET_KEY` config var explicitly. +# Make sure to use a long unique value, like you would for a password. See: +# https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-SECRET_KEY +# https://devcenter.heroku.com/articles/config-vars # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "CHANGE_ME!!!! (P.S. the SECRET_KEY environment variable will be used, if set, instead)." - -if "SECRET_KEY" in os.environ: - SECRET_KEY = os.environ["SECRET_KEY"] +SECRET_KEY = os.environ.get( + "DJANGO_SECRET_KEY", + default=secrets.token_urlsafe(nbytes=64), +) # SECURITY WARNING: don't run with debug turned on in production! if not IS_HEROKU: From 8bac412af73e4cce251841826bfaf0ea34053802 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 19 May 2023 17:28:17 +0100 Subject: [PATCH 092/143] Improve explanation of `ALLOWED_HOSTS` (#202) See: https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-ALLOWED_HOSTS https://devcenter.heroku.com/articles/http-routing --- gettingstarted/settings.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index f4d9eafe0..4671e7b62 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -44,7 +44,10 @@ if not IS_HEROKU: DEBUG = True -# Generally avoid wildcards(*). However since Heroku router provides hostname validation it is ok +# On Heroku, it's safe to use a wildcard for `ALLOWED_HOSTS``, since the Heroku router performs +# validation of the Host header in the incoming HTTP request. On other platforms you may need +# to list the expected hostnames explicitly to prevent HTTP Host header attacks. See: +# https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-ALLOWED_HOSTS if IS_HEROKU: ALLOWED_HOSTS = ["*"] else: From c99a168fa1c9e6277a986c0d86606f0106fdf843 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Sun, 21 May 2023 22:27:37 +0100 Subject: [PATCH 093/143] 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. --- Procfile | 6 ++++ app.json | 1 - gettingstarted/settings.py | 66 ++++++++++++++++---------------------- hello/views.py | 10 ++++++ requirements.txt | 11 +++++-- 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/Procfile b/Procfile index b6f89307b..db56fa856 100644 --- a/Procfile +++ b/Procfile @@ -1 +1,7 @@ web: gunicorn gettingstarted.wsgi + +# Uncomment this `release` process if you are using a database, so that Django's model +# migrations are run as part of app deployment, using Heroku's Release Phase feature: +# https://docs.djangoproject.com/en/4.2/topics/migrations/ +# https://devcenter.heroku.com/articles/release-phase +#release: ./manage.py migrate --no-input diff --git a/app.json b/app.json index 5ac160092..42c60c66b 100644 --- a/app.json +++ b/app.json @@ -4,7 +4,6 @@ "image": "heroku/python", "repository": "https://github.com/heroku/python-getting-started", "keywords": ["python", "django"], - "addons": ["heroku-postgresql"], "env": { "DJANGO_SECRET_KEY": { "description": "The secret key for the Django application.", diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 4671e7b62..f075182b9 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -15,14 +15,11 @@ from pathlib import Path import dj_database_url -from django.test.runner import DiscoverRunner # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent -IS_HEROKU = "DYNO" in os.environ - # Before using your Heroku app in production, make sure to review Django's deployment checklist: # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ @@ -40,15 +37,20 @@ default=secrets.token_urlsafe(nbytes=64), ) +# The `DYNO` env var is set on Heroku CI, but it's not a real Heroku app, so we have to +# also explicitly exclude CI: +# https://devcenter.heroku.com/articles/heroku-ci#immutable-environment-variables +IS_HEROKU_APP = "DYNO" in os.environ and not "CI" in os.environ + # SECURITY WARNING: don't run with debug turned on in production! -if not IS_HEROKU: +if not IS_HEROKU_APP: DEBUG = True # On Heroku, it's safe to use a wildcard for `ALLOWED_HOSTS``, since the Heroku router performs # validation of the Host header in the incoming HTTP request. On other platforms you may need # to list the expected hostnames explicitly to prevent HTTP Host header attacks. See: # https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-ALLOWED_HOSTS -if IS_HEROKU: +if IS_HEROKU_APP: ALLOWED_HOSTS = ["*"] else: ALLOWED_HOSTS = [] @@ -109,25 +111,28 @@ # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases -MAX_CONN_AGE = 600 - -DATABASES = { - "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "db.sqlite3", +if IS_HEROKU_APP: + # In production on Heroku the database configuration is derived from the `DATABASE_URL` + # environment variable by the dj-database-url package. `DATABASE_URL` will be set + # automatically by Heroku when a database addon is attached to your Heroku app. See: + # https://devcenter.heroku.com/articles/provisioning-heroku-postgres + # https://github.com/jazzband/dj-database-url + DATABASES = { + "default": dj_database_url.config( + conn_max_age=600, + conn_health_checks=True, + ssl_require=True, + ), + } +else: + # When running locally in development or in CI, a sqlite database file will be used instead + # to simplify initial setup. Longer term it's recommended to use Postgres locally too. + DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + } } -} - -if "DATABASE_URL" in os.environ: - # Configure Django for DATABASE_URL environment variable. - DATABASES["default"] = dj_database_url.config( - conn_max_age=MAX_CONN_AGE, - ssl_require=True, - ) - - # Enable test database if found in CI environment. - if "CI" in os.environ: - DATABASES["default"]["TEST"] = DATABASES["default"] # Password validation @@ -180,21 +185,6 @@ WHITENOISE_KEEP_ONLY_HASHED_FILES = True -# Test Runner Config -class HerokuDiscoverRunner(DiscoverRunner): - """Test Runner for Heroku CI, which provides a database for you. - This requires you to set the TEST database (done for you by settings().)""" - - def setup_databases(self, **kwargs): - self.keepdb = True - return super(HerokuDiscoverRunner, self).setup_databases(**kwargs) - - -# Use HerokuDiscoverRunner on Heroku CI -if "CI" in os.environ: - TEST_RUNNER = "gettingstarted.settings.HerokuDiscoverRunner" - - # Default primary key field type # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field diff --git a/hello/views.py b/hello/views.py index 79fd8b131..bd7a34b00 100644 --- a/hello/views.py +++ b/hello/views.py @@ -10,6 +10,16 @@ def index(request): def db(request): + # If you encounter errors visiting the `/db/` page on the example app, check that: + # + # When running the app on Heroku: + # 1. You have added the Postgres database to your app. + # 2. You have uncommented the `psycopg` dependency in `requirements.txt`, and the `release` + # process entry in `Procfile`, git committed your changes and re-deployed the app. + # + # When running the app locally: + # 1. You have run `./manage.py migrate` to create the `hello_greeting` database table. + greeting = Greeting() greeting.save() diff --git a/requirements.txt b/requirements.txt index 77c9cba1c..ceeba6c2e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,12 @@ -django>=4.0,<5.0 +django>=4.2,<5.0 gunicorn>=20.0,<21.0 dj-database-url>=2.0,<3.0 whitenoise[brotli]>=6.0,<7.0 -psycopg2>=2.0,<3.0 + +# Uncomment these lines to use a Postgres database. Both are needed, since in production +# (which uses Linux) we want to install from source, so that security updates from the +# underlying Heroku stack image are picked up automatically, thanks to dynamic linking. +# On other platforms/in development, the precompiled binary package is used instead, to +# speed up installation and avoid errors from missing libraries/headers. +#psycopg; sys_platform == "linux" +#psycopg[binary]; sys_platform != "linux" From 5b5a5d7e9a1f0ff5c95b12a3c2df87b0e6e96c6a Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 7 Jun 2023 13:08:11 +0000 Subject: [PATCH 094/143] Update to Python 3.11.4 (#204) https://www.python.org/downloads/release/python-3114/ GUS-W-12512203. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index afe12ad1b..431fc7e8c 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.3 +python-3.11.4 From dea9305fc61ada9c541138ed6f61bcbc21630f7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 12:38:35 +0000 Subject: [PATCH 095/143] Update gunicorn requirement from <21.0,>=20.0 to >=21.2,<22.0 (#205) Updates the requirements on [gunicorn](https://github.com/benoitc/gunicorn) to permit the latest version. - [Release notes](https://github.com/benoitc/gunicorn/releases) - [Commits](https://github.com/benoitc/gunicorn/compare/20.1.0...21.2.0) --- updated-dependencies: - dependency-name: gunicorn dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ceeba6c2e..f01183d61 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ django>=4.2,<5.0 -gunicorn>=20.0,<21.0 +gunicorn>=21.2,<22.0 dj-database-url>=2.0,<3.0 whitenoise[brotli]>=6.0,<7.0 From 7a862828b78de73e13f87c26254be0d16eec1354 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 25 Aug 2023 08:00:36 +0000 Subject: [PATCH 096/143] Update to Python 3.11.5 (#206) https://blog.python.org/2023/08/python-3115-31013-3918-and-3818-is-now.html GUS-W-12512205. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 431fc7e8c..3124d55e9 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.4 +python-3.11.5 From 91ffea496602cba8ed14272e41de87e3a45d54c7 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:32:31 +0100 Subject: [PATCH 097/143] Fix Procfile.windows so it honours `PORT` set by `heroku local` (#207) Ensures that the PORT env var set automatically when running the `heroku local` command is honoured on Windows. GUS-W-14137365. --- Procfile.windows | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile.windows b/Procfile.windows index 69789e554..f593965a1 100644 --- a/Procfile.windows +++ b/Procfile.windows @@ -1 +1 @@ -web: python manage.py runserver 0.0.0.0:5000 +web: python manage.py runserver %PORT% From b4a8c0349268fdb1c14fb0887f8cce5dab4ccf03 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 2 Oct 2023 20:25:38 +0000 Subject: [PATCH 098/143] Update to Python 3.11.6 (#208) https://blog.python.org/2023/10/python-3116-is-now-available.html GUS-W-12512208. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 3124d55e9..76b6e496e 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.5 +python-3.11.6 From 803078eb5f7e7f8e40b350f565ac9b8fe7b1c862 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 4 Oct 2023 07:21:11 +0000 Subject: [PATCH 099/143] Update to Python 3.12.0 (#209) https://blog.python.org/2023/10/python-3120-final-now-available.html https://docs.python.org/3.12/whatsnew/3.12.html GUS-W-12512211. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 76b6e496e..44f8fbe3a 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.6 +python-3.12.0 From f72f4f3e13ba7af904a5f9f4dcc56e19ade821aa Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:53:02 +0000 Subject: [PATCH 100/143] Use the C implementation of psycopg (#210) The `psycopg` package defaults to a pure Python implementation. To opt into the faster C implementation, one has to use the `c` extra. This differs from the `psycopg2` package (which contrary to the what the name suggests, is the older package), where the base package included the C implementation. See: https://www.psycopg.org/psycopg3/docs/basic/install.html#local-installation https://www.psycopg.org/psycopg3/docs/api/pq.html#pq-impl GUS-W-14292989. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f01183d61..f8233da2d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,5 +8,5 @@ whitenoise[brotli]>=6.0,<7.0 # underlying Heroku stack image are picked up automatically, thanks to dynamic linking. # On other platforms/in development, the precompiled binary package is used instead, to # speed up installation and avoid errors from missing libraries/headers. -#psycopg; sys_platform == "linux" +#psycopg[c]; sys_platform == "linux" #psycopg[binary]; sys_platform != "linux" From a422c583d403980474cb84ffa941c5a5fd781507 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 7 Dec 2023 16:08:47 +0000 Subject: [PATCH 101/143] Upgrade to Django 5.0 (#211) I've also regenerated the scaffold project and ported any changes to it over to the project here (which turned out to only be docs URL changes this time). See: https://www.djangoproject.com/weblog/2023/dec/04/django-50-released/ https://docs.djangoproject.com/en/5.0/releases/5.0/ https://docs.djangoproject.com/en/5.0/howto/upgrade-version/ GUS-W-14616121. --- Procfile | 2 +- gettingstarted/asgi.py | 2 +- gettingstarted/settings.py | 24 ++++++++++++------------ gettingstarted/urls.py | 4 ++-- gettingstarted/wsgi.py | 2 +- hello/migrations/0001_initial.py | 2 +- requirements.txt | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Procfile b/Procfile index db56fa856..a760312fc 100644 --- a/Procfile +++ b/Procfile @@ -2,6 +2,6 @@ web: gunicorn gettingstarted.wsgi # Uncomment this `release` process if you are using a database, so that Django's model # migrations are run as part of app deployment, using Heroku's Release Phase feature: -# https://docs.djangoproject.com/en/4.2/topics/migrations/ +# https://docs.djangoproject.com/en/5.0/topics/migrations/ # https://devcenter.heroku.com/articles/release-phase #release: ./manage.py migrate --no-input diff --git a/gettingstarted/asgi.py b/gettingstarted/asgi.py index 7390dd016..ad4e6b1f5 100644 --- a/gettingstarted/asgi.py +++ b/gettingstarted/asgi.py @@ -4,7 +4,7 @@ It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ """ import os diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index f075182b9..356b34e41 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -1,13 +1,13 @@ """ Django settings for gettingstarted project. -Generated by 'django-admin startproject' using Django 4.2.1. +Generated by 'django-admin startproject' using Django 5.0. For more information on this file, see -https://docs.djangoproject.com/en/4.2/topics/settings/ +https://docs.djangoproject.com/en/5.0/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.2/ref/settings/ +https://docs.djangoproject.com/en/5.0/ref/settings/ """ import os @@ -21,7 +21,7 @@ # Before using your Heroku app in production, make sure to review Django's deployment checklist: -# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ # Django requires a unique secret key for each Django app, that is used by several of its # security features. To simplify initial setup (without hardcoding the secret in the source @@ -29,7 +29,7 @@ # Django features break whenever an app restarts (for example, sessions will be logged out). # In your production Heroku apps you should set the `DJANGO_SECRET_KEY` config var explicitly. # Make sure to use a long unique value, like you would for a password. See: -# https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-SECRET_KEY +# https://docs.djangoproject.com/en/5.0/ref/settings/#std-setting-SECRET_KEY # https://devcenter.heroku.com/articles/config-vars # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get( @@ -49,7 +49,7 @@ # On Heroku, it's safe to use a wildcard for `ALLOWED_HOSTS``, since the Heroku router performs # validation of the Host header in the incoming HTTP request. On other platforms you may need # to list the expected hostnames explicitly to prevent HTTP Host header attacks. See: -# https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-ALLOWED_HOSTS +# https://docs.djangoproject.com/en/5.0/ref/settings/#std-setting-ALLOWED_HOSTS if IS_HEROKU_APP: ALLOWED_HOSTS = ["*"] else: @@ -62,7 +62,7 @@ # Use WhiteNoise's runserver implementation instead of the Django default, for dev-prod parity. "whitenoise.runserver_nostatic", # Uncomment this and the entry in `urls.py` if you wish to use the Django admin feature: - # https://docs.djangoproject.com/en/4.2/ref/contrib/admin/ + # https://docs.djangoproject.com/en/5.0/ref/contrib/admin/ # "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", @@ -109,7 +109,7 @@ # Database -# https://docs.djangoproject.com/en/4.2/ref/settings/#databases +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases if IS_HEROKU_APP: # In production on Heroku the database configuration is derived from the `DATABASE_URL` @@ -136,7 +136,7 @@ # Password validation -# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -155,7 +155,7 @@ # Internationalization -# https://docs.djangoproject.com/en/4.2/topics/i18n/ +# https://docs.djangoproject.com/en/5.0/topics/i18n/ LANGUAGE_CODE = "en-us" @@ -167,7 +167,7 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/4.2/howto/static-files/ +# https://docs.djangoproject.com/en/5.0/howto/static-files/ STATIC_ROOT = BASE_DIR / "staticfiles" STATIC_URL = "static/" @@ -186,6 +186,6 @@ # Default primary key field type -# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index 7b1971804..1c221eb5b 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -2,7 +2,7 @@ URL configuration for gettingstarted project. The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/4.2/topics/http/urls/ + https://docs.djangoproject.com/en/5.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views @@ -23,6 +23,6 @@ path("", hello.views.index, name="index"), path("db/", hello.views.db, name="db"), # Uncomment this and the entry in `INSTALLED_APPS` if you wish to use the Django admin feature: - # https://docs.djangoproject.com/en/4.2/ref/contrib/admin/ + # https://docs.djangoproject.com/en/5.0/ref/contrib/admin/ # path("admin/", admin.site.urls), ] diff --git a/gettingstarted/wsgi.py b/gettingstarted/wsgi.py index 4508266fb..5a779d4fc 100644 --- a/gettingstarted/wsgi.py +++ b/gettingstarted/wsgi.py @@ -4,7 +4,7 @@ It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ """ import os diff --git a/hello/migrations/0001_initial.py b/hello/migrations/0001_initial.py index 4e116477b..e0ae6c3bc 100644 --- a/hello/migrations/0001_initial.py +++ b/hello/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.1 on 2023-05-18 12:17 +# Generated by Django 5.0 on 2023-12-07 15:57 from django.db import migrations, models diff --git a/requirements.txt b/requirements.txt index f8233da2d..20c1eb574 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django>=4.2,<5.0 +django>=5.0,<5.1 gunicorn>=21.2,<22.0 dj-database-url>=2.0,<3.0 whitenoise[brotli]>=6.0,<7.0 From 8800360855e4c152fd7e8dad13dccb315cbcf910 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 8 Dec 2023 08:36:21 +0000 Subject: [PATCH 102/143] Update to Python 3.12.1 (#212) https://blog.python.org/2023/12/python-3121-is-now-available.html GUS-W-14232999. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 44f8fbe3a..178174578 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.0 +python-3.12.1 From 738c4a60963e0cb1e0414051f0f2b6f9264d154c Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 2 Feb 2024 10:19:13 +0000 Subject: [PATCH 103/143] Add CODEOWNERS (#216) For parity with our other getting started guides. Docs: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners GUS-W-14825333. --- .github/CODEOWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..55ffb44be --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,8 @@ +# Note: Delete this file if you are copying the code in this repository into your own project. + +# Default to requesting pull request reviews from the Heroku Languages team. +* @heroku/languages + +# However, request review from the Heroku language owner for files that are updated +# by Dependabot, to reduce team review request noise. +requirements.txt @edmorley From 4da63684b28901300c10e2e34ac0726f81b7c288 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 7 Feb 2024 09:54:11 +0000 Subject: [PATCH 104/143] Update to Python 3.12.2 (#217) https://www.python.org/downloads/release/python-3122/ GUS-W-14846695. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 178174578..6e797d468 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.1 +python-3.12.2 From e51d7e335ee26257c7d7dff5dd63f4cb06e44631 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:52:56 +0000 Subject: [PATCH 105/143] Update to Python 3.12.3 (#219) Release announcement: https://www.python.org/downloads/release/python-3123/ Changelog: https://docs.python.org/release/3.12.3/whatsnew/changelog.html#python-3-12-3-final GUS-W-14846713. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 6e797d468..4ddc7cd66 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.2 +python-3.12.3 From 010c9426a81f35b989d8a2860330661da9d8fa26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 07:10:57 +0100 Subject: [PATCH 106/143] Update gunicorn requirement from <22.0,>=21.2 to >=22,<23 (#220) * Update gunicorn requirement from <22.0,>=21.2 to >=21.2,<23.0 Updates the requirements on [gunicorn](https://github.com/benoitc/gunicorn) to permit the latest version. - [Release notes](https://github.com/benoitc/gunicorn/releases) - [Commits](https://github.com/benoitc/gunicorn/compare/21.2.0...22.0.0) --- updated-dependencies: - dependency-name: gunicorn dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Cleanup dependency specifiers --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 20c1eb574..84d51787a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ django>=5.0,<5.1 -gunicorn>=21.2,<22.0 -dj-database-url>=2.0,<3.0 -whitenoise[brotli]>=6.0,<7.0 +gunicorn>=22,<23 +dj-database-url>=2,<3 +whitenoise[brotli]>=6,<7 # Uncomment these lines to use a Postgres database. Both are needed, since in production # (which uses Linux) we want to install from source, so that security updates from the From f15864a6af2f881b177a3c8f31ef86e84be44c03 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 24 May 2024 13:11:32 +0100 Subject: [PATCH 107/143] Improve discoverability of `dj-database-url`'s `env` option (#224) In cases where something other than the `DATABASE_URL` needs to be set, it was previously hard to know how to customise `dj-database-url`'s config, since the upstream docs don't mention the `env` option. Now our default config passes an explicit value for `env` (which matches the default value for that argument), to improve discoverability. In addition, the Heroku Postgres docs link has been updated to deep link to the env vars section, which explains when/why DB env vars will be given alternate colour-prefixed names. Closes #221. --- gettingstarted/settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 356b34e41..225a9b464 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -115,10 +115,11 @@ # In production on Heroku the database configuration is derived from the `DATABASE_URL` # environment variable by the dj-database-url package. `DATABASE_URL` will be set # automatically by Heroku when a database addon is attached to your Heroku app. See: - # https://devcenter.heroku.com/articles/provisioning-heroku-postgres + # https://devcenter.heroku.com/articles/provisioning-heroku-postgres#application-config-vars # https://github.com/jazzband/dj-database-url DATABASES = { "default": dj_database_url.config( + env="DATABASE_URL", conn_max_age=600, conn_health_checks=True, ssl_require=True, From 2d556d9a36c6f4640aee516b4b7853149aa85230 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 27 May 2024 12:10:27 +0100 Subject: [PATCH 108/143] Add `0.0.0.0` to non-production `ALLOWED_HOSTS` (#225) The Dev Center guide instructs users running this project locally to visit `http://localhost:5001`, however, some users don't read the guide properly and instead use the URL output by gunicorn to the logs: ``` [2024-05-27 09:52:07 +0000] [1] [INFO] Listening at: http://0.0.0.0:5001 (1) ``` Django's default debug mode `ALLOWED_HOSTS` only includes `localhost` and `127.0.0.1` etc, so as a result using `0.0.0.0` would result in a `DisallowedHost` error: https://docs.djangoproject.com/en/5.0/ref/settings/#allowed-hosts According to RFC5735 `0.0.0.0` shouldn't be a routable IP, however, browsers and some other clients choose to treat it like localhost: https://stackoverflow.com/a/55646032 Adding it to `ALLOWED_HOSTS` is safe, so we might as well do so to improve the UX when users don't follow the guide properly. See: https://devcenter.heroku.com/admin/articles/feedback/2161#27486 https://devcenter.heroku.com/admin/articles/feedback/2161#27738 GUS-W-14193867. --- gettingstarted/settings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 225a9b464..619f60d88 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -47,13 +47,13 @@ DEBUG = True # On Heroku, it's safe to use a wildcard for `ALLOWED_HOSTS``, since the Heroku router performs -# validation of the Host header in the incoming HTTP request. On other platforms you may need -# to list the expected hostnames explicitly to prevent HTTP Host header attacks. See: +# validation of the Host header in the incoming HTTP request. On other platforms you may need to +# list the expected hostnames explicitly in production to prevent HTTP Host header attacks. See: # https://docs.djangoproject.com/en/5.0/ref/settings/#std-setting-ALLOWED_HOSTS if IS_HEROKU_APP: ALLOWED_HOSTS = ["*"] else: - ALLOWED_HOSTS = [] + ALLOWED_HOSTS = [".localhost", "127.0.0.1", "[::1]", "0.0.0.0"] # Application definition From 7c51913dfe954c806c7712b1f340523b3da8627d Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:17:05 +0100 Subject: [PATCH 109/143] Update Heroku Button URL (#226) To avoid the an additional HTTP 301 redirect. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e937f1b9..0eab837d0 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This application supports the [Getting Started with Python on Heroku](https://de Alternatively, you can deploy it using this Heroku Button: -[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/heroku/python-getting-started) +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://www.heroku.com/deploy?template=https://github.com/heroku/python-getting-started) For more information about using Python on Heroku, see these Dev Center articles: From f3145f313df02f8bf5d19b88f09308a015f11dd1 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:18:11 +0100 Subject: [PATCH 110/143] Update to Python 3.12.4 (#227) Release announcement: https://blog.python.org/2024/06/python-3124-released.html Changelog: https://docs.python.org/3.12/whatsnew/changelog.html GUS-W-15959937. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 4ddc7cd66..74d315a82 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.3 +python-3.12.4 From 6e8b91217dd7ae04af2c54afebd8e8d74e30f049 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:38:21 +0100 Subject: [PATCH 111/143] Update to Python 3.12.5 (#232) Release announcement: https://blog.python.org/2024/08/python-3125-released.html Changelog: https://docs.python.org/release/3.12.5/whatsnew/changelog.html#python-3-12-5 GUS-W-16438131. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 74d315a82..8a7cba521 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.4 +python-3.12.5 From 6b0aa9a99136c31fc27937d3a2895f712cc2c311 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:45:20 +0100 Subject: [PATCH 112/143] Update django requirement from <5.1,>=5.0 to >=5.1,<5.2 (#233) * Update django requirement from <5.1,>=5.0 to >=5.0,<5.2 Updates the requirements on [django](https://github.com/django/django) to permit the latest version. - [Commits](https://github.com/django/django/compare/5.0...5.1) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Correct requirement range * Re sync with upstream Django 5.1 `createproject` output --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- Procfile | 2 +- gettingstarted/asgi.py | 2 +- gettingstarted/settings.py | 24 ++++++++++++------------ gettingstarted/urls.py | 5 +++-- gettingstarted/wsgi.py | 2 +- hello/migrations/0001_initial.py | 2 +- manage.py | 1 + requirements.txt | 2 +- 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Procfile b/Procfile index a760312fc..470556bd9 100644 --- a/Procfile +++ b/Procfile @@ -2,6 +2,6 @@ web: gunicorn gettingstarted.wsgi # Uncomment this `release` process if you are using a database, so that Django's model # migrations are run as part of app deployment, using Heroku's Release Phase feature: -# https://docs.djangoproject.com/en/5.0/topics/migrations/ +# https://docs.djangoproject.com/en/5.1/topics/migrations/ # https://devcenter.heroku.com/articles/release-phase #release: ./manage.py migrate --no-input diff --git a/gettingstarted/asgi.py b/gettingstarted/asgi.py index ad4e6b1f5..09246d692 100644 --- a/gettingstarted/asgi.py +++ b/gettingstarted/asgi.py @@ -4,7 +4,7 @@ It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ """ import os diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 619f60d88..c722f202c 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -1,13 +1,13 @@ """ Django settings for gettingstarted project. -Generated by 'django-admin startproject' using Django 5.0. +Generated by 'django-admin startproject' using Django 5.1. For more information on this file, see -https://docs.djangoproject.com/en/5.0/topics/settings/ +https://docs.djangoproject.com/en/5.1/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/5.0/ref/settings/ +https://docs.djangoproject.com/en/5.1/ref/settings/ """ import os @@ -21,7 +21,7 @@ # Before using your Heroku app in production, make sure to review Django's deployment checklist: -# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ # Django requires a unique secret key for each Django app, that is used by several of its # security features. To simplify initial setup (without hardcoding the secret in the source @@ -29,7 +29,7 @@ # Django features break whenever an app restarts (for example, sessions will be logged out). # In your production Heroku apps you should set the `DJANGO_SECRET_KEY` config var explicitly. # Make sure to use a long unique value, like you would for a password. See: -# https://docs.djangoproject.com/en/5.0/ref/settings/#std-setting-SECRET_KEY +# https://docs.djangoproject.com/en/5.1/ref/settings/#std-setting-SECRET_KEY # https://devcenter.heroku.com/articles/config-vars # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get( @@ -49,7 +49,7 @@ # On Heroku, it's safe to use a wildcard for `ALLOWED_HOSTS``, since the Heroku router performs # validation of the Host header in the incoming HTTP request. On other platforms you may need to # list the expected hostnames explicitly in production to prevent HTTP Host header attacks. See: -# https://docs.djangoproject.com/en/5.0/ref/settings/#std-setting-ALLOWED_HOSTS +# https://docs.djangoproject.com/en/5.1/ref/settings/#std-setting-ALLOWED_HOSTS if IS_HEROKU_APP: ALLOWED_HOSTS = ["*"] else: @@ -62,7 +62,7 @@ # Use WhiteNoise's runserver implementation instead of the Django default, for dev-prod parity. "whitenoise.runserver_nostatic", # Uncomment this and the entry in `urls.py` if you wish to use the Django admin feature: - # https://docs.djangoproject.com/en/5.0/ref/contrib/admin/ + # https://docs.djangoproject.com/en/5.1/ref/contrib/admin/ # "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", @@ -109,7 +109,7 @@ # Database -# https://docs.djangoproject.com/en/5.0/ref/settings/#databases +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases if IS_HEROKU_APP: # In production on Heroku the database configuration is derived from the `DATABASE_URL` @@ -137,7 +137,7 @@ # Password validation -# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -156,7 +156,7 @@ # Internationalization -# https://docs.djangoproject.com/en/5.0/topics/i18n/ +# https://docs.djangoproject.com/en/5.1/topics/i18n/ LANGUAGE_CODE = "en-us" @@ -168,7 +168,7 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/5.0/howto/static-files/ +# https://docs.djangoproject.com/en/5.1/howto/static-files/ STATIC_ROOT = BASE_DIR / "staticfiles" STATIC_URL = "static/" @@ -187,6 +187,6 @@ # Default primary key field type -# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index 1c221eb5b..741113540 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -2,7 +2,7 @@ URL configuration for gettingstarted project. The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/5.0/topics/http/urls/ + https://docs.djangoproject.com/en/5.1/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views @@ -14,6 +14,7 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ + # from django.contrib import admin from django.urls import path @@ -23,6 +24,6 @@ path("", hello.views.index, name="index"), path("db/", hello.views.db, name="db"), # Uncomment this and the entry in `INSTALLED_APPS` if you wish to use the Django admin feature: - # https://docs.djangoproject.com/en/5.0/ref/contrib/admin/ + # https://docs.djangoproject.com/en/5.1/ref/contrib/admin/ # path("admin/", admin.site.urls), ] diff --git a/gettingstarted/wsgi.py b/gettingstarted/wsgi.py index 5a779d4fc..9d8da75b1 100644 --- a/gettingstarted/wsgi.py +++ b/gettingstarted/wsgi.py @@ -4,7 +4,7 @@ It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ """ import os diff --git a/hello/migrations/0001_initial.py b/hello/migrations/0001_initial.py index e0ae6c3bc..5d0aedd71 100644 --- a/hello/migrations/0001_initial.py +++ b/hello/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0 on 2023-12-07 15:57 +# Generated by Django 5.1 on 2024-08-09 09:38 from django.db import migrations, models diff --git a/manage.py b/manage.py index f10541cac..34a1c557c 100755 --- a/manage.py +++ b/manage.py @@ -1,5 +1,6 @@ #!/usr/bin/env python """Django's command-line utility for administrative tasks.""" + import os import sys diff --git a/requirements.txt b/requirements.txt index 84d51787a..e80db5cab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django>=5.0,<5.1 +django>=5.1,<5.2 gunicorn>=22,<23 dj-database-url>=2,<3 whitenoise[brotli]>=6,<7 From d61027fa3e153daf0e89a13db6f8802e02ce9081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Z=C3=BClke?= Date: Wed, 28 Aug 2024 18:05:32 -0400 Subject: [PATCH 113/143] Add viewport meta tag to HTML head (#234) Much better page dimensions and scaling on mobile devices; this tag is standard practice for HTML these days. Also see https://github.com/heroku/php-getting-started/pull/74 --- hello/templates/base.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hello/templates/base.html b/hello/templates/base.html index 97ec07386..73977e0b2 100644 --- a/hello/templates/base.html +++ b/hello/templates/base.html @@ -1,7 +1,8 @@ -Python Getting Started on Heroku + Python Getting Started on Heroku + From 1da36000e9a38658396d111139d6953a10eec05b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 08:49:44 +0100 Subject: [PATCH 114/143] Update gunicorn requirement from <23,>=22 to >=23,<24 (#235) * Update gunicorn requirement from <23,>=22 to >=22,<24 Updates the requirements on [gunicorn](https://github.com/benoitc/gunicorn) to permit the latest version. - [Release notes](https://github.com/benoitc/gunicorn/releases) - [Commits](https://github.com/benoitc/gunicorn/compare/22.0.0...23.0.0) --- updated-dependencies: - dependency-name: gunicorn dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump lower bound --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e80db5cab..c420fa54c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ django>=5.1,<5.2 -gunicorn>=22,<23 +gunicorn>=23,<24 dj-database-url>=2,<3 whitenoise[brotli]>=6,<7 From 295f6efb4be6a0c472cb24ab80f8264298438b18 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Sat, 7 Sep 2024 11:26:20 +0000 Subject: [PATCH 115/143] Update to Python 3.12.6 (#236) https://docs.python.org/release/3.12.6/whatsnew/changelog.html#python-3-12-6-final GUS-W-16690292. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 8a7cba521..32bcba665 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.5 +python-3.12.6 From 60d9aa2cf600edaa7d801e7f6784463ade9811d5 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Tue, 1 Oct 2024 06:31:44 +0000 Subject: [PATCH 116/143] Update to Python 3.12.7 (#237) https://www.python.org/downloads/release/python-3127/ GUS-W-16867262. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 32bcba665..32905d6e0 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.6 +python-3.12.7 From 4d9fb79404f61312c39de4cc4815cf115fe017d8 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 10 Oct 2024 20:59:22 +0000 Subject: [PATCH 117/143] Update to Python 3.13.0 (#238) Release announcement: https://blog.python.org/2024/10/python-3130-final-released.html https://www.python.org/downloads/release/python-3130/ What's new in Python 3.13: https://docs.python.org/3.13/whatsnew/3.13.html GUS-W-14846869. --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 32905d6e0..dae7fec92 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.7 +python-3.13.0 From c9a165d7f7fa08dedcefd76ff83dcc782514198b Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:24:58 +0000 Subject: [PATCH 118/143] Switch from `runtime.txt` to `.python-version` (#239) Since use of the `runtime.txt` file is now deprecated in favour of the `.python-version` file (since the latter is more widely supported in the Python ecosystem). This also switches to specifying only the major Python version (which automatically uses the latest patch release), in order to: 1. Save us from having to bump the version in this repo every time a new Python patch version is released. 2. Ensure that anyone who closes this repo and uses it as the basis for their app is then always using an up to date patch version if they don't know/remember to bump the version themselves. GUS-W-16971647. --- .python-version | 1 + runtime.txt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .python-version delete mode 100644 runtime.txt diff --git a/.python-version b/.python-version new file mode 100644 index 000000000..24ee5b1be --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/runtime.txt b/runtime.txt deleted file mode 100644 index dae7fec92..000000000 --- a/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.13.0 From 0c83b7c202ab0108e50fe95428dd9780424c0653 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:52:03 +0000 Subject: [PATCH 119/143] Disable unused Django features (#240) The example app isn't currently using the admin, auth, sessions and messages features. The config has been commented out rather than removed, to make it easier for users to re-enable if needed. (Particularly since some of the config is order dependant, such as `MIDDLEWARE`.) --- gettingstarted/settings.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index c722f202c..80043c60f 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -58,16 +58,22 @@ # Application definition +# Several optional Django features that are present in the default `startproject` template have +# been disabled since they are not used by this example app. To use them, uncomment the relevant +# entries in `INSTALLED_APPS`, `MIDDLEWARE`, `TEMPLATES` and `urls.py`. See: +# https://docs.djangoproject.com/en/5.1/ref/contrib/admin/ +# https://docs.djangoproject.com/en/5.1/topics/auth/ +# https://docs.djangoproject.com/en/5.1/ref/contrib/contenttypes/ +# https://docs.djangoproject.com/en/5.1/topics/http/sessions/ +# https://docs.djangoproject.com/en/5.1/ref/contrib/messages/ INSTALLED_APPS = [ # Use WhiteNoise's runserver implementation instead of the Django default, for dev-prod parity. "whitenoise.runserver_nostatic", - # Uncomment this and the entry in `urls.py` if you wish to use the Django admin feature: - # https://docs.djangoproject.com/en/5.1/ref/contrib/admin/ # "django.contrib.admin", - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.messages", + # "django.contrib.auth", + # "django.contrib.contenttypes", + # "django.contrib.sessions", + # "django.contrib.messages", "django.contrib.staticfiles", "hello", ] @@ -79,11 +85,11 @@ # after Django's `SecurityMiddleware` so that security redirects are still performed. # See: https://whitenoise.readthedocs.io "whitenoise.middleware.WhiteNoiseMiddleware", - "django.contrib.sessions.middleware.SessionMiddleware", + # "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", - "django.contrib.messages.middleware.MessageMiddleware", + # "django.contrib.auth.middleware.AuthenticationMiddleware", + # "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ] @@ -98,8 +104,8 @@ "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", - "django.contrib.auth.context_processors.auth", - "django.contrib.messages.context_processors.messages", + # "django.contrib.auth.context_processors.auth", + # "django.contrib.messages.context_processors.messages", ], }, }, From 962e79875f43b5c32a9109b416a827023d6f87cd Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:54:27 +0000 Subject: [PATCH 120/143] Configure gunicorn to bind to the IPv6 interface (#241) By default when the `PORT` env var is set, gunicorn binds to the IPv4 interface `0.0.0.0:$PORT`: https://docs.gunicorn.org/en/stable/settings.html#bind Now, we configure it to bind to the IPv6 interface `[::]:$PORT` instead, allowing the app to work in IPv6-only environments. We don't have it bind to both the IPv4 and IPv6 interfaces, since otherwise on Linux by default gunicorn would fail to boot with: ``` [ERROR] connection to ('::', 5006) failed: [Errno 98] Address already in use ``` ...and when binding to the IPv6 interface IPv4 connections will still work (so long as `IPV6_V6ONLY` hasn't been enabled). If this strategy causes issues, we could always start using the `reuse_port` option, however, that makes the DX worse for the local development use-case (it's then possible to leave a stale gunicorn process running, which will serve requests and give the impression code changes aren't taking effect). I've added a `gunicorn.conf.py` config file rather than passing CLI args to the `gunicorn` command, since it allows for more flexibility with the configuration (and there are other settings we'll be adding soon). See: https://docs.gunicorn.org/en/stable/configure.html GUS-W-17280180. --- Procfile | 2 +- gettingstarted/settings.py | 2 +- gunicorn.conf.py | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 gunicorn.conf.py diff --git a/Procfile b/Procfile index 470556bd9..c4512ab32 100644 --- a/Procfile +++ b/Procfile @@ -1,4 +1,4 @@ -web: gunicorn gettingstarted.wsgi +web: gunicorn --config gunicorn.conf.py gettingstarted.wsgi # Uncomment this `release` process if you are using a database, so that Django's model # migrations are run as part of app deployment, using Heroku's Release Phase feature: diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 80043c60f..087b3a776 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -53,7 +53,7 @@ if IS_HEROKU_APP: ALLOWED_HOSTS = ["*"] else: - ALLOWED_HOSTS = [".localhost", "127.0.0.1", "[::1]", "0.0.0.0"] + ALLOWED_HOSTS = [".localhost", "127.0.0.1", "[::1]", "0.0.0.0", "[::]"] # Application definition diff --git a/gunicorn.conf.py b/gunicorn.conf.py new file mode 100644 index 000000000..1db1755e0 --- /dev/null +++ b/gunicorn.conf.py @@ -0,0 +1,16 @@ +# Gunicorn configuration file: +# https://docs.gunicorn.org/en/stable/configure.html +# https://docs.gunicorn.org/en/stable/settings.html +# Note: The classic Python buildpack currently sets a few gunicorn settings automatically via +# the `GUNICORN_CMD_ARGS` env var (which take priority over the settings in this file): +# https://github.com/heroku/heroku-buildpack-python/blob/main/vendor/python.gunicorn.sh + +import os + +# The `PORT` env var is set automatically for web dynos and when using `heroku local`: +# https://devcenter.heroku.com/articles/dyno-startup-behavior#port-binding-of-web-dynos +# https://devcenter.heroku.com/articles/heroku-local +_port = os.environ.get("PORT", 5006) +# Bind to the IPv6 interface instead of the gunicorn default of IPv4, so the app works in IPv6-only +# environments. IPv4 connections will still work so long as `IPV6_V6ONLY` hasn't been enabled. +bind = [f"[::]:{_port}"] From a538e3c0c0ad3f0dab8784fc6abd37dbf0d18034 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 21 Nov 2024 00:57:10 +0000 Subject: [PATCH 121/143] Switch to gunicorn's `gthread` worker type (#242) gunicorn's default worker type is the `sync` worker, which is more suited to CPU/network-bandwidth bound workloads. As such this switches to the thread-based `gthread` worker for improved request throughput performance for blocking I/O workloads - given that it's common for Heroku apps to make blocking requests to external APIs/datastores etc. The threads count of 5 is somewhat arbitrary, but seemed to work well enough with rough benchmarking against a few different dyno sizes (where the process count will vary according to `WEB_CONCURRENCY`) and simulated workload types. The `preload_app` option has also been enabled, which makes gunicorn load the app before the worker processes are forked, to reduce memory usage and boot times. See: https://docs.gunicorn.org/en/stable/design.html#server-model https://docs.gunicorn.org/en/stable/settings.html#worker-class GUS-W-17236632. --- gunicorn.conf.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/gunicorn.conf.py b/gunicorn.conf.py index 1db1755e0..22a2fab6c 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -14,3 +14,37 @@ # Bind to the IPv6 interface instead of the gunicorn default of IPv4, so the app works in IPv6-only # environments. IPv4 connections will still work so long as `IPV6_V6ONLY` hasn't been enabled. bind = [f"[::]:{_port}"] + +# The default `sync` worker is more suited to CPU/network-bandwidth bound workloads, so we +# instead use the thread based worker type for improved support of blocking I/O workloads: +# https://docs.gunicorn.org/en/stable/design.html#server-model +# +# If you need to further improve the performance of blocking I/O workloads, you may want to +# try the `gevent` worker type, though you will need to disable `preload_app`, enable DB +# connecting pooling, and be aware that gevent's monkey patching can break some packages. +# +# Note: When changing the number of dynos/workers/threads you will want to make sure you +# do not exceed the maximum number of connections to external services such as DBs: +# https://devcenter.heroku.com/articles/python-concurrency-and-database-connections +worker_class = "gthread" + +# gunicorn will start this many worker processes. The Python buildpack automatically sets a +# default for WEB_CONCURRENCY at dyno boot, based on the number of CPUs and available RAM: +# https://devcenter.heroku.com/articles/python-concurrency +workers = os.environ.get("WEB_CONCURRENCY", 1) + +# Each `gthread` worker process will use a pool of this many threads. +threads = 5 + +# Load the app before the worker processes are forked, to reduce memory usage and boot times. +preload_app = True + +# Workers silent for more than this many seconds are killed and restarted. +# Note: This only affects the maximum request time when using the `sync` worker. +# For all other worker types it acts only as a worker heartbeat timeout. +timeout = 20 + +# After receiving a restart signal, workers have this much time to finish serving requests. +# This should be set to a value less than the 30 second Heroku dyno shutdown timeout: +# https://devcenter.heroku.com/articles/dyno-shutdown-behavior +graceful_timeout = 20 From 4795062876a634b260fdc69aab907a66267b0112 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:08:23 +0000 Subject: [PATCH 122/143] Update app.json metadata (#243) * Remove the `image` field, since the `heroku.yml` languages feature was sunset some time ago, and the language docker images no longer exist. * Add the `website` field so the Heroku Button deploy form links to the Getting started guide. See: https://devcenter.heroku.com/articles/heroku-button https://devcenter.heroku.com/articles/app-json-schema --- app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.json b/app.json index 42c60c66b..c093460de 100644 --- a/app.json +++ b/app.json @@ -1,8 +1,8 @@ { "name": "Start on Heroku: Python", "description": "A barebones Python app, which can easily be deployed to Heroku.", - "image": "heroku/python", "repository": "https://github.com/heroku/python-getting-started", + "website": "https://devcenter.heroku.com/articles/getting-started-with-python", "keywords": ["python", "django"], "env": { "DJANGO_SECRET_KEY": { From 3d141db2535d117c0021e5fc04448d5de1523986 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:17:24 +0000 Subject: [PATCH 123/143] Clean up the gunicorn `bind` config (#244) So that it's on one line and easier to include via the rundoc template for the getting started guide. --- gunicorn.conf.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gunicorn.conf.py b/gunicorn.conf.py index 22a2fab6c..9332468fd 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -7,13 +7,15 @@ import os -# The `PORT` env var is set automatically for web dynos and when using `heroku local`: +# On Heroku, web dynos must bind to the port number specified via the `PORT` env var. This +# env var is set automatically for web dynos and also when using `heroku local` locally: # https://devcenter.heroku.com/articles/dyno-startup-behavior#port-binding-of-web-dynos # https://devcenter.heroku.com/articles/heroku-local -_port = os.environ.get("PORT", 5006) -# Bind to the IPv6 interface instead of the gunicorn default of IPv4, so the app works in IPv6-only -# environments. IPv4 connections will still work so long as `IPV6_V6ONLY` hasn't been enabled. -bind = [f"[::]:{_port}"] +# Gunicorn will automatically use the `PORT` env var, however, by default it will bind to the +# port using the IPv4 interface (`0.0.0.0`). We configure the binding manually to make it bind +# to the IPv6 interface (`::`) instead, so that the app works in IPv6-only environments too. +# (IPv4 connections will still work so long as `IPV6_V6ONLY` hasn't been enabled.) +bind = ["[::]:{}".format(os.environ.get("PORT", 5006))] # The default `sync` worker is more suited to CPU/network-bandwidth bound workloads, so we # instead use the thread based worker type for improved support of blocking I/O workloads: From 65c908c6ac36428a0be3643a1edb3ce638df51ac Mon Sep 17 00:00:00 2001 From: Richard Schneeman Date: Sun, 8 Dec 2024 08:11:30 -0600 Subject: [PATCH 124/143] Update for Fir (#245) Update the README and app's templates for the release of Fir. Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- README.md | 36 +++++++++++++++++++++++++------ hello/templates/base.html | 36 +++++++++++++++++++++++-------- hello/templates/index.html | 44 ++++++++++++++++++++------------------ 3 files changed, 80 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 0eab837d0..0806f3220 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,44 @@ -# Python: Getting Started +# Python Getting Started A barebones Django app, which can easily be deployed to Heroku. +This application supports the tutorials for both the [Cedar and Fir generations](https://devcenter.heroku.com/articles/generations) of the Heroku platform. You can check them out here: + +- [Getting Started on Heroku with Python](https://devcenter.heroku.com/articles/getting-started-with-python) +- [Getting Started on Heroku Fir with Python](https://devcenter.heroku.com/articles/getting-started-with-python-fir) + ## Deploying to Heroku Using resources for this example app counts towards your usage. [Delete your app](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-apps-destroy) and [database](https://devcenter.heroku.com/articles/heroku-postgresql#removing-the-add-on) as soon as you are done experimenting to control costs. +### Deploy on Heroku [Cedar](https://devcenter.heroku.com/articles/generations#cedar) + By default, apps use Eco dynos if you are subscribed to Eco. Otherwise, it defaults to Basic dynos. The Eco dynos plan is shared across all Eco dynos in your account and is recommended if you plan on deploying many small apps to Heroku. Learn more about our low-cost plans [here](https://blog.heroku.com/new-low-cost-plans). Eligible students can apply for platform credits through our new [Heroku for GitHub Students program](https://blog.heroku.com/github-student-developer-program). -This application supports the [Getting Started with Python on Heroku](https://devcenter.heroku.com/articles/getting-started-with-python) article - check it out for instructions on how to deploy this app to Heroku and also run it locally. - -Alternatively, you can deploy it using this Heroku Button: - -[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://www.heroku.com/deploy?template=https://github.com/heroku/python-getting-started) +```term +$ git clone https://github.com/heroku/python-getting-started +$ cd python-getting-started +$ heroku create +$ git push heroku main +$ heroku open +``` + +### Deploy on Heroku [Fir](https://devcenter.heroku.com/articles/generations#fir) + +By default, apps on [Fir](https://devcenter.heroku.com/articles/generations#fir) use 1X-Classic dynos. To create an app on [Fir](https://devcenter.heroku.com/articles/generations#fir) you'll need to +[create a private space](https://devcenter.heroku.com/articles/working-with-private-spaces#create-a-private-space) +first. + +```term +$ git clone https://github.com/heroku/python-getting-started +$ cd python-getting-started +$ heroku create --space +$ git push heroku main +$ heroku ps:wait +$ heroku open +``` For more information about using Python on Heroku, see these Dev Center articles: diff --git a/hello/templates/base.html b/hello/templates/base.html index 73977e0b2..4a9450c99 100644 --- a/hello/templates/base.html +++ b/hello/templates/base.html @@ -55,20 +55,38 @@ How Heroku Works +