From 1ba77ddb31e296064b074848fcae42fc56e8a0e1 Mon Sep 17 00:00:00 2001 From: V <10897799+VdeJong@users.noreply.github.com> Date: Fri, 17 Mar 2023 11:33:48 +0000 Subject: [PATCH] Feature/wagtail42 chooser (#211) * Update to version 3.22 Based on https://github.com/labd/wagtailstreamforms/issues/200#issuecomment-1373682953, wagtail_generic_chooser is introduced to solve https://github.com/labd/wagtailstreamforms/issues/200. Also, wagtail 4.2 support is added and Django 4.1 * format files * seperate -- from command arg * set max version for wagtail-generic-chooser --- .github/workflows/python-test.yml | 32 +++++++++++++++-- CHANGELOG.rst | 5 +++ setup.py | 4 ++- tests/blocks/test_form_chooser_block.py | 6 +--- tests/hooks/test_process_form.py | 11 +++--- tests/migrations/0001_initial.py | 1 - tox.ini | 6 ++-- wagtailstreamforms/__init__.py | 2 +- wagtailstreamforms/blocks.py | 35 +++++++------------ wagtailstreamforms/migrations/0001_initial.py | 1 - .../migrations/0002_form_site.py | 1 - wagtailstreamforms/streamfield.py | 1 - wagtailstreamforms/views/copy.py | 1 - wagtailstreamforms/wagtail_hooks.py | 27 +++++++++++++- 14 files changed, 87 insertions(+), 46 deletions(-) diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml index 21c00475..d1d8c673 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test.yml @@ -32,6 +32,10 @@ jobs: - py310-dj40-wt30 - py310-dj40-wt40 - py310-dj40-wt41 + - py310-dj40-wt42 + - py310-dj41-wt40 + - py310-dj41-wt41 + - py310-dj41-wt42 - py38-dj32-wt215 - py38-dj32-wt216 - py38-dj32-wt30 @@ -40,7 +44,10 @@ jobs: - py38-dj40-wt216 - py38-dj40-wt30 - py38-dj40-wt40 - - py38-dj40-wt41 + - py38-dj40-wt40 + - py38-dj41-wt41 + - py38-dj41-wt42 + - py38-dj41-wt41 - py39-dj32-wt215 - py39-dj32-wt216 - py39-dj32-wt30 @@ -50,6 +57,9 @@ jobs: - py39-dj40-wt30 - py39-dj40-wt40 - py39-dj40-wt41 + - py39-dj41-wt40 + - py39-dj41-wt41 + - py39-dj41-wt42 include: - python-version: 3.8 tox_env: py38-dj32-wt215 @@ -69,6 +79,12 @@ jobs: tox_env: py38-dj40-wt40 - python-version: 3.8 tox_env: py38-dj40-wt41 + - python-version: 3.8 + tox_env: py38-dj41-wt40 + - python-version: 3.8 + tox_env: py38-dj41-wt41 + - python-version: 3.8 + tox_env: py38-dj41-wt42 - python-version: 3.9 tox_env: py39-dj32-wt215 - python-version: 3.9 @@ -87,6 +103,12 @@ jobs: tox_env: py39-dj40-wt40 - python-version: 3.9 tox_env: py39-dj40-wt41 + - python-version: 3.9 + tox_env: py39-dj41-wt40 + - python-version: 3.9 + tox_env: py39-dj41-wt41 + - python-version: 3.9 + tox_env: py39-dj41-wt42 - python-version: "3.10" tox_env: py310-dj32-wt215 - python-version: "3.10" @@ -105,6 +127,12 @@ jobs: tox_env: py310-dj40-wt40 - python-version: "3.10" tox_env: py310-dj40-wt41 + - python-version: "3.10" + tox_env: py310-dj41-wt40 + - python-version: "3.10" + tox_env: py310-dj41-wt41 + - python-version: "3.10" + tox_env: py310-dj41-wt42 steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -116,7 +144,7 @@ jobs: python -m pip install --upgrade pip pip install tox tox-gh-actions - name: Test with tox - run: tox -e ${{ matrix.tox_env }} --index-url=https://pypi.python.org/simple/ + run: tox -e ${{ matrix.tox_env }} -- index-url=https://pypi.python.org/simple/ - name: Prepare artifacts run: mkdir -p .coverage-data && mv .coverage.* .coverage-data/ - uses: actions/upload-artifact@master diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3de265d5..88f84711 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,11 @@ ********* Changelog ********* +3.22 +---- +* Add Wagtail 4.2 support +* Add Django 4.1 support +* Fix issue with FormChooserBlock 3.21.0 ------ diff --git a/setup.py b/setup.py index 49b5ec43..224c2532 100644 --- a/setup.py +++ b/setup.py @@ -18,8 +18,9 @@ install_requires = [ - "wagtail>=2,<4.2", + "wagtail>=2,<4.3", "Unidecode>=0.04.14,<2.0", + "wagtail-generic-chooser>=0.5.0,<0.6", ] documentation_extras = [ @@ -68,6 +69,7 @@ "Framework :: Django :: 2.2", "Framework :: Django :: 3.2", "Framework :: Django :: 4", + "Framework :: Django :: 4.1", "Framework :: Wagtail", "Framework :: Wagtail :: 2", "Framework :: Wagtail :: 3", diff --git a/tests/blocks/test_form_chooser_block.py b/tests/blocks/test_form_chooser_block.py index abe93854..af417427 100644 --- a/tests/blocks/test_form_chooser_block.py +++ b/tests/blocks/test_form_chooser_block.py @@ -14,15 +14,11 @@ def test_value_for_form(self): block = FormChooserBlock() self.assertEqual(block.value_for_form(self.form.pk), self.form.pk) - self.assertEqual(block.value_for_form(self.form), self.form.pk) + self.assertEqual(block.value_for_form(self.form), self.form) def test_value_from_form(self): block = FormChooserBlock() - # possibly a bug in wagtail as not choosing a value and submitting - # raises invalid literal for int() with base 10: '' - self.assertIsNone(block.value_from_form("")) - self.assertTrue( isinstance(block.value_from_form(self.form.pk), self.form.__class__) ) diff --git a/tests/hooks/test_process_form.py b/tests/hooks/test_process_form.py index 3244e35d..e07e14a8 100644 --- a/tests/hooks/test_process_form.py +++ b/tests/hooks/test_process_form.py @@ -1,12 +1,6 @@ from django.contrib.auth.models import AnonymousUser from django.test import override_settings from django.test.client import Client - -try: - from mock import patch -except ModuleNotFoundError: - from unittest.mock import patch - from wagtail.core.models import Page from wagtailstreamforms.models import Form @@ -14,6 +8,11 @@ from ..test_case import AppTestCase +try: + from mock import patch +except ModuleNotFoundError: + from unittest.mock import patch + class TestHook(AppTestCase): fixtures = ["test.json"] diff --git a/tests/migrations/0001_initial.py b/tests/migrations/0001_initial.py index adc8a935..08ec37d4 100644 --- a/tests/migrations/0001_initial.py +++ b/tests/migrations/0001_initial.py @@ -7,7 +7,6 @@ class Migration(migrations.Migration): - initial = True dependencies = [("wagtailstreamforms", "0001_initial")] diff --git a/tox.ini b/tox.ini index 5826d425..0ab28f5c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,8 @@ [tox] envlist = flake8 - py{38,39,310}-dj{32}-wt{215,216,30,40,41} - py{38,39,310}-dj{40}-wt{216,30,40,41} + py{38,39,310}-dj{32}-wt{215,216,30,40,41,42} + py{38,39,310}-dj{40,41}-wt{216,30,40,41,42} [gh-actions] python = @@ -17,11 +17,13 @@ deps = mock dj32: Django>=3.2,<3.3 dj40: Django>=4.0,<4.1 + dj41: Django>=4.1,<4.2 wt215: wagtail>=2.15,<2.16 wt216: wagtail>=2.16,<2.17 wt30: wagtail>=3.0,<4.0 wt40: wagtail>=4.0,<4.1 wt41: wagtail>=4.1,<4.2 + wt42: wagtail>=4.2,<4.3 commands = coverage run manage.py test diff --git a/wagtailstreamforms/__init__.py b/wagtailstreamforms/__init__.py index e19448ec..71f74e75 100644 --- a/wagtailstreamforms/__init__.py +++ b/wagtailstreamforms/__init__.py @@ -2,6 +2,6 @@ # major.minor.patch.release.number # release must be one of alpha, beta, rc, or final -VERSION = (3, 21, 0, "final", 1) +VERSION = (3, 22, 0, "final", 1) __version__ = get_version(VERSION) diff --git a/wagtailstreamforms/blocks.py b/wagtailstreamforms/blocks.py index c314028d..35431743 100644 --- a/wagtailstreamforms/blocks.py +++ b/wagtailstreamforms/blocks.py @@ -1,11 +1,12 @@ import uuid -from django import forms +from django.utils.functional import cached_property from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ from wagtail.core import blocks from wagtailstreamforms.models import Form +from wagtailstreamforms.wagtail_hooks import WagtailStreamFormsChooser class InfoBlock(blocks.CharBlock): @@ -18,27 +19,16 @@ def render_form(self, value, prefix="", errors=None): class FormChooserBlock(blocks.ChooserBlock): - target_model = Form - widget = forms.Select - - def value_for_form(self, value): - if isinstance(value, self.target_model): - return value.pk - return value - - def value_from_form(self, value): - if value == "": - return None - return super().value_from_form(value) - - def to_python(self, value): - if value is None: - return value - else: - try: - return self.target_model.objects.get(pk=value) - except self.target_model.DoesNotExist: - return None + @cached_property + def target_model(self): + return Form + + @cached_property + def widget(self): + return WagtailStreamFormsChooser() + + def get_form_state(self, value): + return self.widget.get_value_data(value) class WagtailFormBlock(blocks.StructBlock): @@ -75,7 +65,6 @@ def get_context(self, value, parent_context=None): form_reference = value.get("form_reference") if form: - # check the context for an invalid form submitted to the page. # Use that instead if it has the same unique form_reference number invalid_form_reference = context.get("invalid_stream_form_reference") diff --git a/wagtailstreamforms/migrations/0001_initial.py b/wagtailstreamforms/migrations/0001_initial.py index e68b1639..f7e29279 100644 --- a/wagtailstreamforms/migrations/0001_initial.py +++ b/wagtailstreamforms/migrations/0001_initial.py @@ -10,7 +10,6 @@ class Migration(migrations.Migration): - initial = True dependencies = [("wagtailcore", "0040_page_draft_title")] diff --git a/wagtailstreamforms/migrations/0002_form_site.py b/wagtailstreamforms/migrations/0002_form_site.py index e5ae79b5..56116a5e 100644 --- a/wagtailstreamforms/migrations/0002_form_site.py +++ b/wagtailstreamforms/migrations/0002_form_site.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - dependencies = [("wagtailstreamforms", "0001_initial")] operations = [ diff --git a/wagtailstreamforms/streamfield.py b/wagtailstreamforms/streamfield.py index c5cd98ee..3a6761ff 100644 --- a/wagtailstreamforms/streamfield.py +++ b/wagtailstreamforms/streamfield.py @@ -20,7 +20,6 @@ def __init__(self, local_blocks=None, **kwargs): self._child_blocks = self.base_blocks.copy() for name, field_class in get_fields().items(): - # ensure the field is a subclass of BaseField. if not issubclass(field_class, BaseField): raise ImproperlyConfigured( diff --git a/wagtailstreamforms/views/copy.py b/wagtailstreamforms/views/copy.py index 242a0746..060cc341 100644 --- a/wagtailstreamforms/views/copy.py +++ b/wagtailstreamforms/views/copy.py @@ -51,7 +51,6 @@ def copy(self, request, *args, **kwargs): form = CopyForm(request.POST) if form.is_valid(): - copied = self.object.copy() copied.title = form.cleaned_data["title"] copied.slug = form.cleaned_data["slug"] diff --git a/wagtailstreamforms/wagtail_hooks.py b/wagtailstreamforms/wagtail_hooks.py index a793a7ba..20842b38 100644 --- a/wagtailstreamforms/wagtail_hooks.py +++ b/wagtailstreamforms/wagtail_hooks.py @@ -4,6 +4,8 @@ from django.template.response import TemplateResponse from django.urls import include, path, reverse from django.utils.translation import gettext_lazy as _ +from generic_chooser.views import ModelChooserViewSet +from generic_chooser.widgets import AdminChooser from wagtail.admin import messages as wagtail_messages from wagtail.contrib.modeladmin.helpers import AdminURLHelper, ButtonHelper from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register @@ -85,7 +87,7 @@ def get_buttons_for_obj( ) ) - # users that can do any form actions can vies submissions + # users that can do any form actions can view submissions buttons.append( self.button( pk, @@ -245,3 +247,26 @@ def process_form(page, request, *args, **kwargs): return TemplateResponse( request, page.get_template(request, *args, **kwargs), context ) + + +class WagtailStreamFormsChooserViewSet(ModelChooserViewSet): + icon = "form" + model = Form + page_title = _("Choose a form") + per_page = 10 + + +class WagtailStreamFormsChooser(AdminChooser): + choose_one_text = _("Choose a form") + choose_another_text = _("Choose another form") + link_to_chosen_text = _("Edit this form") + model = Form + choose_modal_url_name = "wagtailstreamforms_chooser:choose" + icon = "form" + + +@hooks.register("register_admin_viewset") +def register_wagtailstreamforms_chooser_viewset(): + return WagtailStreamFormsChooserViewSet( + "wagtailstreamforms_chooser", url_prefix="wagtailstreamforms-chooser" + )