diff --git a/.circleci/config.yml b/.circleci/config.yml
index cad7e23..d7d8490 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -59,6 +59,9 @@ workflows:
- build-and-test:
wagtail-version: "wagtail>=2.16,<2.17"
python-version: "3.10"
+ - build-and-test:
+ wagtail-version: "wagtail>=3.0,<3.1"
+ python-version: "3.10"
nightly:
jobs:
- nightly-wagtail-test
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index edf602f..f3db547 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,12 @@
Changelog
=========
+Unreleased
+~~~~~~~~~~~~~~~~~~
+
+ * Add support for Wagtail 3.0 (William Blackie)
+
+
0.8.4 (09.06.2022)
~~~~~~~~~~~~~~~~~~
diff --git a/setup.py b/setup.py
index 385735d..4c7de5d 100644
--- a/setup.py
+++ b/setup.py
@@ -38,5 +38,6 @@
'Framework :: Django',
'Framework :: Wagtail',
'Framework :: Wagtail :: 2',
+ 'Framework :: Wagtail :: 3',
],
)
diff --git a/tests/blocks.py b/tests/blocks.py
index 9e4e098..3afd5b9 100644
--- a/tests/blocks.py
+++ b/tests/blocks.py
@@ -1,6 +1,12 @@
-from wagtail.core.blocks import (
- CharBlock, IntegerBlock, RichTextBlock, StreamBlock, StructBlock, ListBlock, PageChooserBlock
-)
+from wagtail import VERSION as WAGTAIL_VERSION
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail.blocks import (
+ CharBlock, IntegerBlock, RichTextBlock, StreamBlock, StructBlock, ListBlock, PageChooserBlock
+ )
+else:
+ from wagtail.core.blocks import (
+ CharBlock, IntegerBlock, RichTextBlock, StreamBlock, StructBlock, ListBlock, PageChooserBlock
+ )
class CaptionedPageLink(StructBlock):
diff --git a/tests/migrations/0004_pagewithrichtext.py b/tests/migrations/0004_pagewithrichtext.py
index d31cc89..a0bac62 100644
--- a/tests/migrations/0004_pagewithrichtext.py
+++ b/tests/migrations/0004_pagewithrichtext.py
@@ -2,8 +2,12 @@
from django.db import migrations, models
import django.db.models.deletion
-import wagtail.core.fields
+from wagtail import VERSION as WAGTAIL_VERSION
+if WAGTAIL_VERSION >= (3, 0):
+ import wagtail.fields as wagtail_fields
+else:
+ import wagtail.core.fields as wagtail_fields
class Migration(migrations.Migration):
@@ -17,7 +21,7 @@ class Migration(migrations.Migration):
name='PageWithRichText',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
- ('body', wagtail.core.fields.RichTextField(max_length=255)),
+ ('body', wagtail_fields.RichTextField(max_length=255)),
],
options={
'abstract': False,
diff --git a/tests/migrations/0005_pagewithstreamfield.py b/tests/migrations/0005_pagewithstreamfield.py
index 601c7ce..5803823 100644
--- a/tests/migrations/0005_pagewithstreamfield.py
+++ b/tests/migrations/0005_pagewithstreamfield.py
@@ -2,8 +2,14 @@
from django.db import migrations, models
import django.db.models.deletion
-import wagtail.core.blocks
-import wagtail.core.fields
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ import wagtail.blocks as wagtail_blocks
+ import wagtail.fields as wagtail_fields
+else:
+ import wagtail.core.blocks as wagtail_blocks
+ import wagtail.core.fields as wagtail_fields
class Migration(migrations.Migration):
@@ -18,7 +24,7 @@ class Migration(migrations.Migration):
name='PageWithStreamField',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
- ('body', wagtail.core.fields.StreamField([('link_block', wagtail.core.blocks.StructBlock([('page', wagtail.core.blocks.PageChooserBlock()), ('text', wagtail.core.blocks.CharBlock(max_length=250))])), ('page', wagtail.core.blocks.PageChooserBlock()), ('stream', wagtail.core.blocks.StreamBlock([('page', wagtail.core.blocks.PageChooserBlock())])), ('rich_text', wagtail.core.blocks.RichTextBlock()), ('list_of_pages', wagtail.core.blocks.ListBlock(wagtail.core.blocks.PageChooserBlock()))], blank=True, verbose_name='Page body')),
+ ('body', wagtail_fields.StreamField([('link_block', wagtail_blocks.StructBlock([('page', wagtail_blocks.PageChooserBlock()), ('text', wagtail_blocks.CharBlock(max_length=250))])), ('page', wagtail_blocks.PageChooserBlock()), ('stream', wagtail_blocks.StreamBlock([('page', wagtail_blocks.PageChooserBlock())])), ('rich_text', wagtail_blocks.RichTextBlock()), ('list_of_pages', wagtail_blocks.ListBlock(wagtail_blocks.PageChooserBlock()))], blank=True, verbose_name='Page body')),
],
options={
'abstract': False,
diff --git a/tests/migrations/0013_pagechooserblock_nonrequired.py b/tests/migrations/0013_pagechooserblock_nonrequired.py
index 00c68a6..36b0b01 100644
--- a/tests/migrations/0013_pagechooserblock_nonrequired.py
+++ b/tests/migrations/0013_pagechooserblock_nonrequired.py
@@ -1,8 +1,15 @@
# Generated by Django 3.0.4 on 2020-03-25 17:38
from django.db import migrations
-import wagtail.core.blocks
-import wagtail.core.fields
+
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ import wagtail.blocks as wagtail_blocks
+ import wagtail.fields as wagtail_fields
+else:
+ import wagtail.core.blocks as wagtail_blocks
+ import wagtail.core.fields as wagtail_fields
class Migration(migrations.Migration):
@@ -15,6 +22,6 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='pagewithstreamfield',
name='body',
- field=wagtail.core.fields.StreamField([('link_block', wagtail.core.blocks.StructBlock([('page', wagtail.core.blocks.PageChooserBlock(required=False)), ('text', wagtail.core.blocks.CharBlock(max_length=250))])), ('page', wagtail.core.blocks.PageChooserBlock()), ('stream', wagtail.core.blocks.StreamBlock([('page', wagtail.core.blocks.PageChooserBlock())])), ('rich_text', wagtail.core.blocks.RichTextBlock()), ('list_of_pages', wagtail.core.blocks.ListBlock(wagtail.core.blocks.PageChooserBlock()))], blank=True, verbose_name='Page body'),
+ field=wagtail_fields.StreamField([('link_block', wagtail_blocks.StructBlock([('page', wagtail_blocks.PageChooserBlock(required=False)), ('text', wagtail_blocks.CharBlock(max_length=250))])), ('page', wagtail_blocks.PageChooserBlock()), ('stream', wagtail_blocks.StreamBlock([('page', wagtail_blocks.PageChooserBlock())])), ('rich_text', wagtail_blocks.RichTextBlock()), ('list_of_pages', wagtail_blocks.ListBlock(wagtail_blocks.PageChooserBlock()))], blank=True, verbose_name='Page body'),
),
]
diff --git a/tests/migrations/0014_rich_text_nullable.py b/tests/migrations/0014_rich_text_nullable.py
index 7e6b2ae..cae5ba1 100644
--- a/tests/migrations/0014_rich_text_nullable.py
+++ b/tests/migrations/0014_rich_text_nullable.py
@@ -1,7 +1,12 @@
# Generated by Django 3.0.4 on 2020-03-30 10:25
from django.db import migrations
-import wagtail.core.fields
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ import wagtail.fields as wagtail_fields
+else:
+ import wagtail.core.fields as wagtail_fields
class Migration(migrations.Migration):
@@ -14,6 +19,6 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='pagewithrichtext',
name='body',
- field=wagtail.core.fields.RichTextField(blank=True, max_length=255, null=True),
+ field=wagtail_fields.RichTextField(blank=True, max_length=255, null=True),
),
]
diff --git a/tests/migrations/0018_alter_pagewithrelatedpages_related_pages_and_more.py b/tests/migrations/0018_alter_pagewithrelatedpages_related_pages_and_more.py
index d5bc3b4..9c6062c 100644
--- a/tests/migrations/0018_alter_pagewithrelatedpages_related_pages_and_more.py
+++ b/tests/migrations/0018_alter_pagewithrelatedpages_related_pages_and_more.py
@@ -1,8 +1,14 @@
# Generated by Django 4.0 on 2022-06-09 15:17
from django.db import migrations, models
-import wagtail.core.blocks
-import wagtail.core.fields
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ import wagtail.blocks as wagtail_blocks
+ import wagtail.fields as wagtail_fields
+else:
+ import wagtail.core.blocks as wagtail_blocks
+ import wagtail.core.fields as wagtail_fields
class Migration(migrations.Migration):
@@ -20,6 +26,6 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='pagewithstreamfield',
name='body',
- field=wagtail.core.fields.StreamField([('link_block', wagtail.core.blocks.StructBlock([('page', wagtail.core.blocks.PageChooserBlock(required=False)), ('text', wagtail.core.blocks.CharBlock(max_length=250))])), ('integer', wagtail.core.blocks.IntegerBlock(required=True)), ('page', wagtail.core.blocks.PageChooserBlock()), ('stream', wagtail.core.blocks.StreamBlock([('page', wagtail.core.blocks.PageChooserBlock())])), ('rich_text', wagtail.core.blocks.RichTextBlock()), ('list_of_pages', wagtail.core.blocks.ListBlock(wagtail.core.blocks.PageChooserBlock())), ('list_of_captioned_pages', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('page', wagtail.core.blocks.PageChooserBlock(required=False)), ('text', wagtail.core.blocks.CharBlock(max_length=250))])))], blank=True, verbose_name='Page body'),
+ field=wagtail_fields.StreamField([('link_block', wagtail_blocks.StructBlock([('page', wagtail_blocks.PageChooserBlock(required=False)), ('text', wagtail_blocks.CharBlock(max_length=250))])), ('integer', wagtail_blocks.IntegerBlock(required=True)), ('page', wagtail_blocks.PageChooserBlock()), ('stream', wagtail_blocks.StreamBlock([('page', wagtail_blocks.PageChooserBlock())])), ('rich_text', wagtail_blocks.RichTextBlock()), ('list_of_pages', wagtail_blocks.ListBlock(wagtail_blocks.PageChooserBlock())), ('list_of_captioned_pages', wagtail_blocks.ListBlock(wagtail_blocks.StructBlock([('page', wagtail_blocks.PageChooserBlock(required=False)), ('text', wagtail_blocks.CharBlock(max_length=250))])))], blank=True, verbose_name='Page body'),
),
]
diff --git a/tests/models.py b/tests/models.py
index 127e53b..8723208 100644
--- a/tests/models.py
+++ b/tests/models.py
@@ -1,11 +1,16 @@
from django.db import models
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from taggit.managers import TaggableManager
-from wagtail.core.fields import RichTextField, StreamField
-from wagtail.core.models import Orderable, Page
from wagtail.snippets.models import register_snippet
-
from .blocks import BaseStreamBlock
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail.fields import RichTextField, StreamField
+ from wagtail.models import Orderable, Page
+else:
+ from wagtail.core.fields import RichTextField, StreamField
+ from wagtail.core.models import Orderable, Page
class SimplePage(Page):
diff --git a/tests/settings.py b/tests/settings.py
index c6e2236..23bf1cd 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -1,6 +1,7 @@
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+from wagtail import VERSION as WAGTAIL_VERSION
# Quick-start development settings - unsuitable for production
@@ -8,7 +9,6 @@
# Application definition
-
INSTALLED_APPS = [
'tests',
'wagtail_transfer',
@@ -36,6 +36,12 @@
'django.contrib.staticfiles',
]
+# wagtail.core is now found in wagtail in Wagtail^=3.0
+if WAGTAIL_VERSION >= (3, 0):
+ INSTALLED_APPS[
+ INSTALLED_APPS.index('wagtail.core')
+ ] = "wagtail"
+
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
diff --git a/tests/tests/test_api.py b/tests/tests/test_api.py
index 84ebafc..c96388e 100644
--- a/tests/tests/test_api.py
+++ b/tests/tests/test_api.py
@@ -10,7 +10,6 @@
from django.core.files.images import ImageFile
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase, override_settings
-from wagtail.core.models import Page, Collection
from wagtail.images.models import Image
from wagtail.documents.models import Document
@@ -22,7 +21,11 @@
)
from .utils import has_new_listblock_format
-
+from wagtail import VERSION as WAGTAIL_VERSION
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail.models import Page, Collection
+else:
+ from wagtail.core.models import Page, Collection
# We could use settings.MEDIA_ROOT here, but this way we avoid clobbering a real media folder if we
# ever run these tests with non-test settings for any reason
diff --git a/tests/tests/test_import.py b/tests/tests/test_import.py
index 6ea31d4..84595b4 100644
--- a/tests/tests/test_import.py
+++ b/tests/tests/test_import.py
@@ -1,4 +1,3 @@
-from ensurepip import version
import importlib
import os.path
import shutil
@@ -9,7 +8,6 @@
from django.contrib.contenttypes.models import ContentType
from django.core.files.images import ImageFile
from django.test import TestCase, override_settings
-from wagtail.core.models import Collection, Page
from wagtail.images.models import Image
from wagtail_transfer.models import IDMapping
@@ -20,6 +18,11 @@
)
from .utils import has_new_listblock_format
+from wagtail import VERSION as WAGTAIL_VERSION
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail.models import Page, Collection
+else:
+ from wagtail.core.models import Page, Collection
# We could use settings.MEDIA_ROOT here, but this way we avoid clobbering a real media folder if we
# ever run these tests with non-test settings for any reason
@@ -434,7 +437,10 @@ def test_import_page_with_child_models(self):
def test_import_page_with_comments(self):
try:
- from wagtail.core.models import Comment
+ if WAGTAIL_VERSION >= (3, 0):
+ from wagtail.models import Comment
+ else:
+ from wagtail.core.models import Comment
except ImportError:
self.skipTest("Comments not available on this version of Wagtail")
data = """{
diff --git a/tests/urls.py b/tests/urls.py
index d83d65f..2a10358 100644
--- a/tests/urls.py
+++ b/tests/urls.py
@@ -1,10 +1,14 @@
from __future__ import absolute_import, unicode_literals
from django.urls import include, re_path
-
from wagtail.admin import urls as wagtailadmin_urls
-from wagtail.core import urls as wagtail_urls
from wagtail_transfer import urls as wagtailtransfer_urls
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail import urls as wagtail_urls
+else:
+ from wagtail.core import urls as wagtail_urls
urlpatterns = [
diff --git a/wagtail_transfer/field_adapters.py b/wagtail_transfer/field_adapters.py
index cd4a5b4..fb0724d 100644
--- a/wagtail_transfer/field_adapters.py
+++ b/wagtail_transfer/field_adapters.py
@@ -12,8 +12,6 @@
from django.utils.functional import cached_property
from modelcluster.fields import ParentalKey
from taggit.managers import TaggableManager
-from wagtail.core import hooks
-from wagtail.core.fields import RichTextField, StreamField
from .files import File, FileTransferError, get_file_hash, get_file_size
from .locators import get_locator_for_model
@@ -25,6 +23,16 @@
from django.utils.encoding import is_protected_type
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail import hooks
+ from wagtail.fields import RichTextField, StreamField
+else:
+ from wagtail.core import hooks
+ from wagtail.core.fields import RichTextField, StreamField
+
+
WAGTAILTRANSFER_FOLLOWED_REVERSE_RELATIONS = getattr(settings, "WAGTAILTRANSFER_FOLLOWED_REVERSE_RELATIONS", [('wagtailimages.image', 'tagged_items', True)])
FOLLOWED_REVERSE_RELATIONS = {
(model_label.lower(), relation.lower()) for model_label, relation, _ in WAGTAILTRANSFER_FOLLOWED_REVERSE_RELATIONS
diff --git a/wagtail_transfer/operations.py b/wagtail_transfer/operations.py
index 81b49c9..6c14551 100644
--- a/wagtail_transfer/operations.py
+++ b/wagtail_transfer/operations.py
@@ -6,13 +6,18 @@
from django.db import models, transaction
from modelcluster.models import ClusterableModel, get_all_child_relations
from treebeard.mp_tree import MP_Node
-from wagtail.core.models import Page
-
from .field_adapters import adapter_registry
from .locators import get_locator_for_model
from .models import get_base_model, get_base_model_for_path, get_model_for_path
from django.utils.functional import cached_property
+from wagtail import VERSION as WAGTAIL_VERSION
+
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail.models import Page
+else:
+ from wagtail.core.models import Page
+
# Models which should be updated to their latest version when encountered in object references
default_update_related_models = ['wagtailimages.image']
diff --git a/wagtail_transfer/richtext.py b/wagtail_transfer/richtext.py
index e9b330c..987ec38 100644
--- a/wagtail_transfer/richtext.py
+++ b/wagtail_transfer/richtext.py
@@ -1,10 +1,15 @@
import re
from functools import partial
+from .models import get_base_model
-from wagtail.core.rich_text import features
-from wagtail.core.rich_text.rewriters import extract_attrs
+from wagtail import VERSION as WAGTAIL_VERSION
-from .models import get_base_model
+if WAGTAIL_VERSION >= (3, 0):
+ from wagtail.rich_text import features
+ from wagtail.rich_text.rewriters import extract_attrs
+else:
+ from wagtail.core.rich_text import features
+ from wagtail.core.rich_text.rewriters import extract_attrs
FIND_A_TAG = re.compile(r']*)>(.*?)')
FIND_EMBED_TAG = re.compile(r'