diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 94b383fc4..cd36c7d0f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: '3.12' cache: 'pip' cache-dependency-path: 'requirements/*.txt' - name: Install dependencies diff --git a/Dockerfile b/Dockerfile index 338e9f8ff..d5806bf8f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-slim +dwFROM python:3.12-slim # Install packages needed to run your application (not build deps): # We need to recreate the /usr/share/man/man{1..8} directories first because @@ -33,7 +33,7 @@ RUN set -ex \ zlib1g-dev \ " \ && apt-get update && apt-get install -y --no-install-recommends $BUILD_DEPS \ - && python3.9 -m venv ${VIRTUAL_ENV} \ + && python3.12 -m venv ${VIRTUAL_ENV} \ && pip install -U pip \ && pip install --no-cache-dir -r /requirements/production.txt \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $BUILD_DEPS \ diff --git a/bakerydemo/base/management/commands/reset_demo.py b/bakerydemo/base/management/commands/reset_demo.py index c3a609ac9..aa4c5a268 100644 --- a/bakerydemo/base/management/commands/reset_demo.py +++ b/bakerydemo/base/management/commands/reset_demo.py @@ -17,7 +17,7 @@ def handle(self, **options): ) # 1. (optional) Remove all objects from S3 - if "s3" in settings.DEFAULT_FILE_STORAGE: + if "s3" in settings.STORAGES["default"]["BACKEND"]: self.stdout.write("Removing files from S3") default_storage.bucket.objects.all().delete() else: diff --git a/bakerydemo/base/models.py b/bakerydemo/base/models.py index 3ae5335f2..26c809954 100644 --- a/bakerydemo/base/models.py +++ b/bakerydemo/base/models.py @@ -12,6 +12,7 @@ PublishingPanel, ) from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField +from wagtail.contrib.forms.panels import FormSubmissionsPanel from wagtail.contrib.settings.models import ( BaseGenericSetting, BaseSiteSetting, @@ -436,6 +437,7 @@ class FormPage(AbstractEmailForm): # Note how we include the FormField object via an InlinePanel using the # related_name value content_panels = AbstractEmailForm.content_panels + [ + FormSubmissionsPanel(), FieldPanel("image"), FieldPanel("body"), InlinePanel("form_fields", heading="Form fields", label="Field"), diff --git a/bakerydemo/base/templatetags/navigation_tags.py b/bakerydemo/base/templatetags/navigation_tags.py index 75699dd26..ba32c1e39 100644 --- a/bakerydemo/base/templatetags/navigation_tags.py +++ b/bakerydemo/base/templatetags/navigation_tags.py @@ -4,7 +4,7 @@ from bakerydemo.base.models import FooterText register = template.Library() -# https://docs.djangoproject.com/en/3.2/howto/custom-template-tags/ +# https://docs.djangoproject.com/en/stable/howto/custom-template-tags/ @register.simple_tag(takes_context=True) diff --git a/bakerydemo/settings/base.py b/bakerydemo/settings/base.py index 68ff436e6..108fffdd7 100644 --- a/bakerydemo/settings/base.py +++ b/bakerydemo/settings/base.py @@ -4,10 +4,10 @@ Generated by 'django-admin startproject' using Django 1.10.5. For more information on this file, see -https://docs.djangoproject.com/en/3.2/topics/settings/ +https://docs.djangoproject.com/en/stable/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/3.2/ref/settings/ +https://docs.djangoproject.com/en/stable/ref/settings/ """ import os @@ -19,7 +19,7 @@ BASE_DIR = os.path.dirname(PROJECT_DIR) # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/stable/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = "c6u0-9c!7nilj_ysatsda0(f@e_2mws2f!6m0n^o*4#*q#kzp)" @@ -116,7 +116,7 @@ # Database -# https://docs.djangoproject.com/en/3.2/ref/settings/#databases +# https://docs.djangoproject.com/en/stable/ref/settings/#databases if "DATABASE_URL" in os.environ: DATABASES = {"default": dj_database_url.config(conn_max_age=500)} @@ -130,7 +130,7 @@ # Password validation -# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/stable/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -149,7 +149,7 @@ # Internationalization -# https://docs.djangoproject.com/en/3.2/topics/i18n/ +# https://docs.djangoproject.com/en/stable/topics/i18n/ LANGUAGE_CODE = "en-us" @@ -157,13 +157,19 @@ USE_I18N = True -USE_L10N = True - -USE_TZ = True - +# All storages to be used with Django. +# https://docs.djangoproject.com/en/stable/ref/settings/#storages +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + }, +} # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/3.2/howto/static-files/ +# https://docs.djangoproject.com/en/stable/howto/static-files/ STATICFILES_FINDERS = [ "django.contrib.staticfiles.finders.FileSystemFinder", diff --git a/bakerydemo/settings/production.py b/bakerydemo/settings/production.py index 28847766b..2d453ec15 100644 --- a/bakerydemo/settings/production.py +++ b/bakerydemo/settings/production.py @@ -24,7 +24,7 @@ # Accept all hostnames, since we don't know in advance which hostname will be used for any given Heroku instance. # IMPORTANT: Set this to a real hostname when using this in production! -# See https://docs.djangoproject.com/en/3.2/ref/settings/#allowed-hosts +# See https://docs.djangoproject.com/en/stable/ref/settings/#allowed-hosts ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "*").split(",") EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" @@ -141,13 +141,13 @@ # https://warehouse.python.org/project/whitenoise/ MIDDLEWARE.append("whitenoise.middleware.WhiteNoiseMiddleware") -STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" +STORAGES["staticfiles"]["BACKEND"] = "whitenoise.storage.CompressedManifestStaticFilesStorage" if "AWS_STORAGE_BUCKET_NAME" in os.environ: AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME") AWS_QUERYSTRING_AUTH = False INSTALLED_APPS.append("storages") - DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" + STORAGES["default"]["BACKEND"] = "storages.backends.s3boto3.S3Boto3Storage" AWS_S3_FILE_OVERWRITE = False AWS_DEFAULT_ACL = "private" if "AWS_S3_CUSTOM_DOMAIN" in os.environ: @@ -162,7 +162,7 @@ GS_AUTO_CREATE_BUCKET = True INSTALLED_APPS.append("storages") - DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage" + STORAGES["default"]["BACKEND"] = "storages.backends.gcloud.GoogleCloudStorage" LOGGING = { "version": 1, @@ -186,7 +186,7 @@ # These settings are usually used only on the production sites. # This is a configuration of the CDN/front-end cache that is used to cache the # production websites. -# https://docs.wagtail.org/en/latest/reference/contrib/frontendcache.html +# https://docs.wagtail.org/en/stable/reference/contrib/frontendcache.html # The backend can be configured to use an account-wide API key, or an API token with # restricted access. if ( @@ -225,26 +225,28 @@ # Basic authentication settings # These are settings to configure the third-party library: # https://gitlab.com/tmkn/django-basic-auth-ip-whitelist -if os.environ.get("BASIC_AUTH_ENABLED", "false").lower().strip() == "true": - # Insert basic auth as a first middleware to be checked first, before - # anything else. - MIDDLEWARE.insert(0, "baipw.middleware.BasicAuthIPWhitelistMiddleware") +# Commented out until django-basic-auth-ip-whitelist supports Django 5.0. +# See https://github.com/tm-kn/django-basic-auth-ip-whitelist/pull/15. +# if os.environ.get("BASIC_AUTH_ENABLED", "false").lower().strip() == "true": +# # Insert basic auth as a first middleware to be checked first, before +# # anything else. +# MIDDLEWARE.insert(0, "baipw.middleware.BasicAuthIPWhitelistMiddleware") - # This is the credentials users will have to use to access the site. - BASIC_AUTH_LOGIN = os.environ.get("BASIC_AUTH_LOGIN", "wagtail") - BASIC_AUTH_PASSWORD = os.environ.get("BASIC_AUTH_PASSWORD", "wagtail") +# # This is the credentials users will have to use to access the site. +# BASIC_AUTH_LOGIN = os.environ.get("BASIC_AUTH_LOGIN", "wagtail") +# BASIC_AUTH_PASSWORD = os.environ.get("BASIC_AUTH_PASSWORD", "wagtail") - # Wagtail requires Authorization header to be present for the previews - BASIC_AUTH_DISABLE_CONSUMING_AUTHORIZATION_HEADER = True +# # Wagtail requires Authorization header to be present for the previews +# BASIC_AUTH_DISABLE_CONSUMING_AUTHORIZATION_HEADER = True - # This is the list of hosts that website can be accessed without basic auth - # check. - if "BASIC_AUTH_WHITELISTED_HTTP_HOSTS" in os.environ: - BASIC_AUTH_WHITELISTED_HTTP_HOSTS = os.environ[ - "BASIC_AUTH_WHITELISTED_HTTP_HOSTS" - ].split(",") +# # This is the list of hosts that website can be accessed without basic auth +# # check. +# if "BASIC_AUTH_WHITELISTED_HTTP_HOSTS" in os.environ: +# BASIC_AUTH_WHITELISTED_HTTP_HOSTS = os.environ[ +# "BASIC_AUTH_WHITELISTED_HTTP_HOSTS" +# ].split(",") - BASIC_AUTH_RESPONSE_TEMPLATE = "base/basic_auth.html" +# BASIC_AUTH_RESPONSE_TEMPLATE = "base/basic_auth.html" # Force HTTPS redirect (enabled by default!) @@ -271,7 +273,7 @@ # because the apps are running on client domains (or our own for staging), that are # being used for other applications as well. We should therefore not impose any # restrictions on these unrelated applications. -# https://docs.djangoproject.com/en/3.2/ref/settings/#secure-hsts-include-subdomains +# https://docs.djangoproject.com/en/stable/ref/settings/#secure-hsts-include-subdomains SECURE_HSTS_INCLUDE_SUBDOMAINS = False # https://docs.djangoproject.com/en/stable/ref/settings/#secure-browser-xss-filter @@ -288,5 +290,5 @@ ).strip() # Allow the redirect importer to work in load-balanced / cloud environments. -# https://docs.wagtail.io/en/v2.13/reference/settings.html#redirects +# https://docs.wagtail.org/en/stable/reference/settings.html#redirects WAGTAIL_REDIRECTS_FILE_STORAGE = "cache" diff --git a/bakerydemo/templates/base/form_page.html b/bakerydemo/templates/base/form_page.html index 022623508..6f3a06fe3 100644 --- a/bakerydemo/templates/base/form_page.html +++ b/bakerydemo/templates/base/form_page.html @@ -24,7 +24,7 @@

{{ page.title }}

{% comment %} You could render your form using a Django rendering shortcut such as `{{ form.as_p }}` but that will tend towards unsemantic code, and make it difficult to style. You can read more on Django form at: - https://docs.djangoproject.com/en/3.2/topics/forms/#form-rendering-options + https://docs.djangoproject.com/en/stable/topics/forms/#working-with-form-templates {% endcomment %}
{% csrf_token %} diff --git a/bakerydemo/wsgi.py b/bakerydemo/wsgi.py index 376970f94..98bca514e 100644 --- a/bakerydemo/wsgi.py +++ b/bakerydemo/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/3.2/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/stable/howto/deployment/wsgi/ """ import os diff --git a/readme.md b/readme.md index a93248115..b352eefcc 100644 --- a/readme.md +++ b/readme.md @@ -121,11 +121,11 @@ docker compose logs -f ## Setup with Virtualenv -You can run the Wagtail demo locally without setting up Vagrant or Docker and simply use Virtualenv, which is the [recommended installation approach](https://docs.djangoproject.com/en/3.2/topics/install/#install-the-django-code) for Django itself. +You can run the Wagtail demo locally without setting up Vagrant or Docker and simply use Virtualenv, which is the [recommended installation approach](https://docs.djangoproject.com/en/stable/topics/install/#install-the-django-code) for Django itself. #### Dependencies -- Python 3.7, 3.8, 3.9, 3.10 or 3.11 +- Python 3.10, 3.11, 3.12 - [Virtualenv](https://virtualenv.pypa.io/en/stable/installation/) - [VirtualenvWrapper](https://virtualenvwrapper.readthedocs.io/en/latest/install.html) (optional) @@ -141,7 +141,7 @@ Confirm that this is showing a compatible version of Python 3.x. If not, and you deactivate rmvirtualenv wagtailbakerydemo - mkvirtualenv wagtailbakerydemo --python=python3.9 + mkvirtualenv wagtailbakerydemo --python=python3.12 python --version Now we're ready to set up the bakery demo project itself: @@ -206,7 +206,7 @@ In production on your own site, you'll need to change this to: `EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'` -and configure [SMTP settings](https://docs.djangoproject.com/en/3.2/topics/email/#smtp-backend) appropriate for your email provider. +and configure [SMTP settings](https://docs.djangoproject.com/en/stable/topics/email/#smtp-backend) appropriate for your email provider. ### Testing Content-Security-Policy compliance in Wagtail diff --git a/requirements/base.txt b/requirements/base.txt index e51113da8..d141d5b00 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,4 +1,4 @@ -Django>=4.2,<4.3 +Django>=5.0,<5.1 django-dotenv==1.4.2 wagtail>=5.2,<5.3 wagtail-font-awesome-svg>=1,<2 diff --git a/requirements/production.txt b/requirements/production.txt index 6694dc0a0..f757f62b4 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -11,4 +11,6 @@ django-storages==1.14.2 botocore>=1.12.33,<1.13 aws-requests-auth==0.4.3 django-redis==5.4.0 -django-basic-auth-ip-whitelist==0.5 +# Commented out until django-basic-auth-ip-whitelist supports Django 5.0. +# See https://github.com/tm-kn/django-basic-auth-ip-whitelist/pull/15. +# django-basic-auth-ip-whitelist==0.5 diff --git a/runtime.txt b/runtime.txt index 250d1e3df..178174578 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.2 +python-3.12.1