kopia lustrzana https://github.com/wagtail/wagtail
Drop support for Django 2.2
rodzic
9b1156210c
commit
85c97fe87f
|
@ -17,9 +17,8 @@ on:
|
|||
# - test runs with USE_EMAIL_USER_MODEL=yes and DISABLE_TIMEZONE=yes
|
||||
|
||||
# Current configuration:
|
||||
# - django 2.2, python 3.6, mysql
|
||||
# - django 3.0, python 3.7, sqlite
|
||||
# - django 3.1, python 3.8, postgres
|
||||
# - django 3.0, python 3.6, sqlite
|
||||
# - django 3.1, python 3.7, postgres
|
||||
# - django 3.2, python 3.8, postgres
|
||||
# - django 3.2, python 3.9, mysql
|
||||
# - django 3.2, python 3.9, sqlite
|
||||
|
@ -27,9 +26,8 @@ on:
|
|||
# - django 3.2, python 3.9, postgres, DISABLE_TIMEZONE=yes
|
||||
# - django stable/3.2.x, python 3.9, postgres (allow failures)
|
||||
# - django main, python 3.9, postgres (allow failures)
|
||||
# - elasticsearch 5, django 2.2, python 3.6, sqlite
|
||||
# - elasticsearch 6, django 3.0, python 3.7, postgres
|
||||
# - elasticsearch 7, django 3.1, python 3.8, postgres
|
||||
# - elasticsearch 5, django 3.0, python 3.6, sqlite
|
||||
# - elasticsearch 6, django 3.1, python 3.7, postgres
|
||||
# - elasticsearch 7, django 3.2, python 3.8, postgres
|
||||
# - elasticsearch 7, django 3.2, python 3.9, sqlite, USE_EMAIL_USER_MODEL=yes
|
||||
|
||||
|
@ -39,7 +37,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.7
|
||||
- python: 3.6
|
||||
django: "Django>=3.0,<3.1"
|
||||
- python: 3.9
|
||||
django: "Django>=3.1,<3.2"
|
||||
|
@ -67,7 +65,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.8
|
||||
- python: 3.7
|
||||
django: "Django>=3.1,<3.2"
|
||||
experimental: false
|
||||
- python: 3.8
|
||||
|
@ -123,8 +121,6 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.6
|
||||
django: "Django>=2.2,<3.0"
|
||||
- python: 3.9
|
||||
django: "Django>=3.2,<3.3"
|
||||
|
||||
|
@ -166,7 +162,7 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- python: 3.6
|
||||
django: "Django>=2.2,<3.0"
|
||||
django: "Django>=3.0,<3.1"
|
||||
steps:
|
||||
- name: Configure sysctl limits
|
||||
run: |
|
||||
|
@ -250,7 +246,7 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- python: 3.7
|
||||
django: "Django>=3.0,<3.1"
|
||||
django: "Django>=3.1,<3.2"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
|
@ -297,8 +293,6 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.8
|
||||
django: "Django>=3.1,<3.2"
|
||||
- python: 3.8
|
||||
django: "Django>=3.2,<3.3"
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ Changelog
|
|||
2.14 (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Removed support for Django 2.2
|
||||
* Added ``ancestor_of`` API filter (Jaap Roes)
|
||||
* Fix: Invalid filter values for foreign key fields in the API now give an error instead of crashing (Tidjani Dia)
|
||||
* Fix: Ordering specified in `construct_explorer_page_queryset` hook is now taken into account again by the page explorer API (Andre Fonseca)
|
||||
|
|
|
@ -56,11 +56,11 @@ _(If you are reading this on GitHub, the details here may not be indicative of t
|
|||
|
||||
Wagtail supports:
|
||||
|
||||
* Django 2.2.x, 3.0.x, 3.1.x and 3.2.x
|
||||
* Django 3.0.x, 3.1.x and 3.2.x
|
||||
* Python 3.6, 3.7, 3.8 and 3.9
|
||||
* PostgreSQL, MySQL and SQLite as database backends
|
||||
|
||||
[Previous versions of Wagtail](https://docs.wagtail.io/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7 and Django 1.x.
|
||||
[Previous versions of Wagtail](https://docs.wagtail.io/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7 and Django 1.x - 2.x.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
Wagtail provides the `wagtail start` command and project template to get you started with a new Wagtail project as quickly as possible, but it's easy to integrate Wagtail into an existing Django project too.
|
||||
|
||||
Wagtail is currently compatible with Django 2.2, 3.0, 3.1 and 3.2. First, install the `wagtail` package from PyPI:
|
||||
Wagtail is currently compatible with Django 3.0, 3.1 and 3.2. First, install the `wagtail` package from PyPI:
|
||||
|
||||
```sh
|
||||
$ pip install wagtail
|
||||
|
|
|
@ -24,3 +24,8 @@ Bug fixes
|
|||
|
||||
Upgrade considerations
|
||||
======================
|
||||
|
||||
Removed support for Django 2.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Django 2.2 is no longer supported as of this release; please upgrade to Django 3.0 or above before upgrading Wagtail.
|
||||
|
|
3
setup.py
3
setup.py
|
@ -20,7 +20,7 @@ except ImportError:
|
|||
|
||||
|
||||
install_requires = [
|
||||
"Django>=2.2,<3.3",
|
||||
"Django>=3.0,<3.3",
|
||||
"django-modelcluster>=5.1,<6.0",
|
||||
"django-taggit>=1.0,<2.0",
|
||||
"django-treebeard>=4.2.0,<5.0,!=4.5",
|
||||
|
@ -109,7 +109,6 @@ https://github.com/wagtail/wagtail/.",
|
|||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
'Framework :: Django',
|
||||
'Framework :: Django :: 2.2',
|
||||
'Framework :: Django :: 3.0',
|
||||
'Framework :: Django :: 3.1',
|
||||
'Framework :: Django :: 3.2',
|
||||
|
|
3
tox.ini
3
tox.ini
|
@ -2,7 +2,7 @@
|
|||
skipsdist = True
|
||||
usedevelop = True
|
||||
|
||||
envlist = py{36,37,38,39}-dj{22,30,31,32,32stable,main}-{sqlite,postgres,mysql,mssql}-{elasticsearch7,elasticsearch6,elasticsearch5,noelasticsearch}-{customuser,emailuser}-{tz,notz},
|
||||
envlist = py{36,37,38,39}-dj{30,31,32,32stable,main}-{sqlite,postgres,mysql,mssql}-{elasticsearch7,elasticsearch6,elasticsearch5,noelasticsearch}-{customuser,emailuser}-{tz,notz},
|
||||
|
||||
[testenv]
|
||||
install_command = pip install -e ".[testing]" -U {opts} {packages}
|
||||
|
@ -22,7 +22,6 @@ deps =
|
|||
django-sendfile==0.3.6
|
||||
Embedly
|
||||
|
||||
dj22: Django~=2.2.0
|
||||
dj30: Django~=3.0.0
|
||||
dj31: Django~=3.1.0
|
||||
dj32: Django~=3.2.0
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django import VERSION as DJANGO_VERSION
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase
|
||||
|
@ -319,14 +318,9 @@ class TestPageCopy(TestCase, WagtailTestUtils):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check that a form error was raised
|
||||
if DJANGO_VERSION >= (3, 0):
|
||||
self.assertFormError(
|
||||
response, 'form', 'new_slug', "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens."
|
||||
)
|
||||
else:
|
||||
self.assertFormError(
|
||||
response, 'form', 'new_slug', "Enter a valid 'slug' consisting of Unicode letters, numbers, underscores, or hyphens."
|
||||
)
|
||||
self.assertFormError(
|
||||
response, 'form', 'new_slug', "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens."
|
||||
)
|
||||
|
||||
def test_page_copy_post_valid_unicode_slug(self):
|
||||
post_data = {
|
||||
|
|
|
@ -2,7 +2,6 @@ import unittest
|
|||
|
||||
import pytz
|
||||
|
||||
from django import VERSION as DJANGO_VERSION
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth import views as auth_views
|
||||
|
@ -344,10 +343,7 @@ class TestAccountSection(TestCase, WagtailTestUtils, TestAccountSectionUtilsMixi
|
|||
# Check that a validation error was raised
|
||||
password_form = password_panel.get_form()
|
||||
self.assertTrue('new_password2' in password_form.errors.keys())
|
||||
if DJANGO_VERSION >= (3, 0):
|
||||
self.assertTrue("The two password fields didn’t match." in password_form.errors['new_password2'])
|
||||
else:
|
||||
self.assertTrue("The two password fields didn't match." in password_form.errors['new_password2'])
|
||||
self.assertTrue("The two password fields didn’t match." in password_form.errors['new_password2'])
|
||||
|
||||
# Check that the password was not changed
|
||||
self.user.refresh_from_db()
|
||||
|
@ -722,10 +718,7 @@ class TestPasswordReset(TestCase, WagtailTestUtils):
|
|||
self.password_reset_uid = force_str(urlsafe_base64_encode(force_bytes(self.user.pk)))
|
||||
|
||||
# Create url_args
|
||||
if DJANGO_VERSION >= (3, 0):
|
||||
token = auth_views.PasswordResetConfirmView.reset_url_token
|
||||
else:
|
||||
token = auth_views.INTERNAL_RESET_URL_TOKEN
|
||||
token = auth_views.PasswordResetConfirmView.reset_url_token
|
||||
|
||||
self.url_kwargs = dict(uidb64=self.password_reset_uid, token=token)
|
||||
|
||||
|
@ -807,11 +800,7 @@ class TestPasswordReset(TestCase, WagtailTestUtils):
|
|||
|
||||
# Check that a validation error was raised
|
||||
self.assertTrue('new_password2' in response.context['form'].errors.keys())
|
||||
|
||||
if DJANGO_VERSION >= (3, 0):
|
||||
self.assertTrue("The two password fields didn’t match." in response.context['form'].errors['new_password2'])
|
||||
else:
|
||||
self.assertTrue("The two password fields didn't match." in response.context['form'].errors['new_password2'])
|
||||
self.assertTrue("The two password fields didn’t match." in response.context['form'].errors['new_password2'])
|
||||
|
||||
# Check that the password was not changed
|
||||
self.assertTrue(get_user_model().objects.get(email='test@email.com').check_password('password'))
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from datetime import timedelta
|
||||
|
||||
from django import VERSION as DJANGO_VERSION
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
@ -85,30 +84,17 @@ class TestAuditLogAdmin(TestCase, WagtailTestUtils):
|
|||
self.assertContains(response, "Page scheduled for publishing", 1)
|
||||
self.assertContains(response, "Published", 1)
|
||||
|
||||
if DJANGO_VERSION >= (3, 0):
|
||||
self.assertContains(
|
||||
response, "Added the 'Private, accessible to logged-in users' view restriction"
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
"Updated the view restriction to 'Private, accessible with the following password'"
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
"Removed the 'Private, accessible with the following password' view restriction"
|
||||
)
|
||||
else:
|
||||
self.assertContains(
|
||||
response, "Added the 'Private, accessible to logged-in users' view restriction"
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
"Updated the view restriction to 'Private, accessible with the following password'"
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
"Removed the 'Private, accessible with the following password' view restriction"
|
||||
)
|
||||
self.assertContains(
|
||||
response, "Added the 'Private, accessible to logged-in users' view restriction"
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
"Updated the view restriction to 'Private, accessible with the following password'"
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
"Removed the 'Private, accessible with the following password' view restriction"
|
||||
)
|
||||
|
||||
self.assertContains(response, 'system', 2) # create without a user + remove restriction
|
||||
self.assertContains(response, 'the_editor', 9) # 7 entries by editor + 1 in sidebar menu + 1 in filter
|
||||
|
|
|
@ -126,7 +126,7 @@ class ModelAdmin(WagtailRegisterable):
|
|||
self.model, self.inspect_view_enabled)
|
||||
self.url_helper = self.get_url_helper_class()(self.model)
|
||||
|
||||
# Needed to support RelatedFieldListFilter in Django 2.2+
|
||||
# Needed to support RelatedFieldListFilter
|
||||
# See: https://github.com/wagtail/wagtail/issues/5105
|
||||
self.admin_site = default_django_admin_site
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django import VERSION as DJANGO_VERSION
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.test import TestCase
|
||||
|
||||
|
@ -65,21 +64,13 @@ class TestExcludeFromExplorer(TestCase, WagtailTestUtils):
|
|||
def test_attribute_effects_explorer(self):
|
||||
# The two VenuePages should appear in the venuepage list
|
||||
response = self.client.get('/admin/modeladmintest/venuepage/')
|
||||
if DJANGO_VERSION >= (3, 0):
|
||||
self.assertContains(response, "Santa's Grotto")
|
||||
self.assertContains(response, "Santa's Workshop")
|
||||
else:
|
||||
self.assertContains(response, "Santa's Grotto")
|
||||
self.assertContains(response, "Santa's Workshop")
|
||||
self.assertContains(response, "Santa's Grotto")
|
||||
self.assertContains(response, "Santa's Workshop")
|
||||
|
||||
# But when viewing the children of 'Christmas' event in explorer
|
||||
response = self.client.get('/admin/pages/4/')
|
||||
if DJANGO_VERSION >= (3, 0):
|
||||
self.assertNotContains(response, "Santa's Grotto")
|
||||
self.assertNotContains(response, "Santa's Workshop")
|
||||
else:
|
||||
self.assertNotContains(response, "Santa's Grotto")
|
||||
self.assertNotContains(response, "Santa's Workshop")
|
||||
self.assertNotContains(response, "Santa's Grotto")
|
||||
self.assertNotContains(response, "Santa's Workshop")
|
||||
|
||||
# But the other test page should...
|
||||
self.assertContains(response, "Claim your free present!")
|
||||
|
|
|
@ -33,16 +33,12 @@ from wagtail.admin.views.mixins import SpreadsheetExportMixin
|
|||
from .forms import ParentChooserForm
|
||||
|
||||
|
||||
try:
|
||||
from django.db.models.sql.constants import QUERY_TERMS
|
||||
except ImportError:
|
||||
# Django 2.1+ does not have QUERY_TERMS anymore
|
||||
QUERY_TERMS = {
|
||||
'contains', 'day', 'endswith', 'exact', 'gt', 'gte', 'hour',
|
||||
'icontains', 'iendswith', 'iexact', 'in', 'iregex', 'isnull',
|
||||
'istartswith', 'lt', 'lte', 'minute', 'month', 'range', 'regex',
|
||||
'search', 'second', 'startswith', 'week_day', 'year',
|
||||
}
|
||||
QUERY_TERMS = {
|
||||
'contains', 'day', 'endswith', 'exact', 'gt', 'gte', 'hour',
|
||||
'icontains', 'iendswith', 'iexact', 'in', 'iregex', 'isnull',
|
||||
'istartswith', 'lt', 'lte', 'minute', 'month', 'range', 'regex',
|
||||
'search', 'second', 'startswith', 'week_day', 'year',
|
||||
}
|
||||
|
||||
|
||||
class WMABaseView(TemplateView):
|
||||
|
@ -255,7 +251,7 @@ class IndexView(SpreadsheetExportMixin, WMABaseView):
|
|||
IGNORED_PARAMS = (ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, EXPORT_VAR)
|
||||
|
||||
# sortable_by is required by the django.contrib.admin.templatetags.admin_list.result_headers
|
||||
# template tag as of Django 2.1 - see https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.sortable_by
|
||||
# template tag - see https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.sortable_by
|
||||
sortable_by = None
|
||||
|
||||
@method_decorator(login_required)
|
||||
|
|
|
@ -7,7 +7,6 @@ from collections import namedtuple
|
|||
from io import StringIO
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from django import VERSION as DJANGO_VERSION
|
||||
from django import forms
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
|
@ -96,17 +95,13 @@ def _extract_field_data(source, exclude_fields=None):
|
|||
if isinstance(field, models.OneToOneField) and field.remote_field.parent_link:
|
||||
continue
|
||||
|
||||
if DJANGO_VERSION >= (3, 0) and isinstance(field, models.ForeignKey):
|
||||
if isinstance(field, models.ForeignKey):
|
||||
# Use attname to copy the ID instead of retrieving the instance
|
||||
|
||||
# Note: We first need to set the field to None to unset any object
|
||||
# that's there already just setting _id on its own won't change the
|
||||
# field until its saved.
|
||||
|
||||
# Before Django 3.0, Django won't find the new object if the field
|
||||
# was set to None in this way, so this optimisation isn't available
|
||||
# for Django 2.x.
|
||||
|
||||
data_dict[field.name] = None
|
||||
data_dict[field.attname] = getattr(source, field.attname)
|
||||
|
||||
|
|
|
@ -2,18 +2,13 @@ from django.conf import settings
|
|||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
|
||||
from wagtail.core import hooks
|
||||
from wagtail.core.forms import PasswordViewRestrictionForm
|
||||
from wagtail.core.models import Page, PageViewRestriction, Site
|
||||
|
||||
|
||||
try:
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
except ImportError: # fallback for Django 2.2
|
||||
from django.utils.http import is_safe_url as url_has_allowed_host_and_scheme
|
||||
|
||||
|
||||
def serve(request, path):
|
||||
# we need a valid Site object corresponding to this request in order to proceed
|
||||
site = Site.find_for_request(request)
|
||||
|
|
|
@ -5,6 +5,7 @@ from django.http import Http404, HttpResponse, StreamingHttpResponse
|
|||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.urls import reverse
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.views.decorators.cache import cache_control
|
||||
from django.views.decorators.http import etag
|
||||
|
||||
|
@ -17,12 +18,6 @@ from wagtail.utils import sendfile_streaming_backend
|
|||
from wagtail.utils.sendfile import sendfile
|
||||
|
||||
|
||||
try:
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
except ImportError: # fallback for Django 2.2
|
||||
from django.utils.http import is_safe_url as url_has_allowed_host_and_scheme
|
||||
|
||||
|
||||
def document_etag(request, document_id, document_filename):
|
||||
Document = get_document_model()
|
||||
if hasattr(Document, 'file_hash'):
|
||||
|
|
Ładowanie…
Reference in New Issue