This is a sample Python application deployed to Heroku. It's a reasonably simple app - but a good foundation for understanding how to get the most out of the Heroku platform.
-
-
- To deploy your own copy, and learn the fundamentals of the Heroku platform, head over to the
Getting Started with Python on Heroku tutorial.
+
+ To deploy your own copy, and learn the fundamentals of the Heroku platform, head over to either of the following tutorials:
+
-
+
How this sample app works
- - 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 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.
+ - This app was deployed to Heroku using Git.
+ - When Heroku received the source code, it fetched all the dependencies in requirements.txt, creating a deployable build artifact.
+ - The platform then spins up a dyno, a lightweight container that provides an isolated environment in which the build artifact can be mounted and executed.
- You can scale your app, manage it, and deploy over 150 add-on services, from the Dashboard or CLI.
Next Steps
- - If you are following the Getting Started guide, then please head back to the tutorial and follow the next steps!
- - If you deployed this app by deploying the Heroku Button, then in a command line shell, run:
-
- git clone https://github.com/heroku/python-getting-started.git - this will create a local copy of the source code for the app
- cd python-getting-started - change directory into the local source code repository
- heroku git:remote -a <your-app-name> - associate the Heroku app with the repository
- - You'll now be set up to run the app locally, or deploy changes to Heroku
-
+ - If you are following the Getting Started on Heroku with Python or Getting Started on Heroku Fir with Python guide, then please head back to the tutorial and follow the next steps!
Helpful Links
-
-
- Please do work through the Getting Started guide, even if you do know how to build such an application. The guide covers the basics of working with Heroku, and will familiarize you with all the concepts you need in order to build and deploy your own apps.
+
+
+
+
+ Please do work through the Getting Started guide, even if you do know how to build such an application. The guide covers the basics of working with Heroku, and will familiarize you with all the concepts you need in order to build and deploy your own apps.
+
+
{% endblock %}
diff --git a/hello/tests.py b/hello/tests.py
index 9b06366a5..8134bff8b 100644
--- a/hello/tests.py
+++ b/hello/tests.py
@@ -1,19 +1,26 @@
-from django.contrib.auth.models import AnonymousUser, User
-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)
diff --git a/hello/views.py b/hello/views.py
index c2480724b..bd7a34b00 100644
--- a/hello/views.py
+++ b/hello/views.py
@@ -1,15 +1,24 @@
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):
+ # 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/manage.py b/manage.py
index eb3ab8af5..34a1c557c 100755
--- a/manage.py
+++ b/manage.py
@@ -1,10 +1,23 @@
#!/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()
diff --git a/project.toml b/project.toml
new file mode 100644
index 000000000..ec4f08cbd
--- /dev/null
+++ b/project.toml
@@ -0,0 +1,19 @@
+[_]
+schema-version = "0.2"
+
+[io.buildpacks]
+# Exclude files from local Pack CLI builds, where .gitignore doesn't apply.
+# TODO: Add trailing slash to entries that are directories, once this issue is fixed:
+# https://github.com/buildpacks/pack/issues/2402
+exclude = [
+ "__pycache__",
+ ".git",
+ ".gitignore",
+ ".github",
+ ".venv",
+ ".DS_Store",
+ ".env",
+ "staticfiles",
+ "db.sqlite3",
+ "venv",
+]
diff --git a/requirements.txt b/requirements.txt
index 4af6a3765..db5f46b0f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,7 @@
-django
-gunicorn
-django-heroku
\ No newline at end of file
+django>=6.1,<6.2
+gunicorn>=26,<27
+dj-database-url>=3,<4
+whitenoise>=6,<7
+
+# Uncomment to use a Postgres database.
+#psycopg[binary]
diff --git a/runtime.txt b/runtime.txt
deleted file mode 100644
index 9bff0e00f..000000000
--- a/runtime.txt
+++ /dev/null
@@ -1 +0,0 @@
-python-3.9.6