From 9e5e97ccdaeffb2e70745bc8002780a401a963bb Mon Sep 17 00:00:00 2001 From: Stuart George Date: Sun, 17 Jun 2018 20:27:55 +0100 Subject: [PATCH 1/2] better streamfield init --- tests/fields/test_streamfield.py | 56 +++++++++++++++++++++++++++++++ wagtailstreamforms/streamfield.py | 42 +++++++++++++++++++++-- 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 tests/fields/test_streamfield.py diff --git a/tests/fields/test_streamfield.py b/tests/fields/test_streamfield.py new file mode 100644 index 00000000..05421ec2 --- /dev/null +++ b/tests/fields/test_streamfield.py @@ -0,0 +1,56 @@ +from django import forms +from django.core.exceptions import ImproperlyConfigured + +from wagtailstreamforms.streamfield import FormFieldsStreamField +from wagtailstreamforms import fields + +from ..test_case import AppTestCase + + +class GoodField(fields.BaseField): + field_class = forms.CharField + + +class TestCorrectTypeRegistering(AppTestCase): + + @classmethod + def setUpClass(cls): + fields.register('good', GoodField) + + @classmethod + def tearDownClass(cls): + del fields._fields['good'] + + def test_child_blocks(self): + field = FormFieldsStreamField([]) + self.assertIn('good', field.stream_block.child_blocks) + + def test_dependencies(self): + field = FormFieldsStreamField([]) + self.assertListEqual( + [b.__class__ for b in field.stream_block.dependencies], + [b.__class__ for b in field.stream_block.child_blocks.values()] + ) + + +class BadField: + field_class = forms.CharField + + +class TestIncorrectTypeRegistering(AppTestCase): + + @classmethod + def setUpClass(cls): + fields.register('bad', BadField) + + @classmethod + def tearDownClass(cls): + del fields._fields['bad'] + + def test_is_invalid_class(self): + expected_error = "'%s' must be a subclass of '%s'" % (BadField, fields.BaseField) + + with self.assertRaises(ImproperlyConfigured) as e: + FormFieldsStreamField([]) + + self.assertEqual(e.exception.args[0], expected_error) diff --git a/wagtailstreamforms/streamfield.py b/wagtailstreamforms/streamfield.py index aaecced3..7a290188 100644 --- a/wagtailstreamforms/streamfield.py +++ b/wagtailstreamforms/streamfield.py @@ -1,10 +1,46 @@ +from django.core.exceptions import ImproperlyConfigured + +from wagtail.core import blocks from wagtail.core.fields import StreamField +from wagtailstreamforms.fields import get_fields, BaseField -from wagtailstreamforms.fields import get_fields +class FormFieldStreamBlock(blocks.StreamBlock): + """ Add all registered instances of BaseField's get_form_block method to the streamfield. """ -class FormFieldsStreamField(StreamField): + def __init__(self, local_blocks=None, **kwargs): + self._constructor_kwargs = kwargs + + # Note, this is calling BaseStreamBlock's super __init__, not FormFieldStreamBlock's. + # We don't want BaseStreamBlock.__init__() to run, because it tries to assign to self.child_blocks, + # which we've overridden with a @property. But we DO want Block.__init__() to run. + super(blocks.BaseStreamBlock, self).__init__() + + 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("'%s' must be a subclass of '%s'" % (field_class, BaseField)) + # assign the block + block = field_class().get_form_block() + block.set_name(name) + self._child_blocks[name] = block + + self._dependencies = self._child_blocks.values() + + @property + def child_blocks(self): + return self._child_blocks + + @property + def dependencies(self): + return self._dependencies + + +class FormFieldsStreamField(StreamField): def __init__(self, block_types, **kwargs): - block_types = [(key, item().get_form_block()) for key, item in get_fields().items()] super().__init__(block_types, **kwargs) + self.stream_block = FormFieldStreamBlock(block_types, required=not self.blank) From fadb66d800729bb03cfbc37e695d93c345b9da94 Mon Sep 17 00:00:00 2001 From: Stuart George Date: Mon, 18 Jun 2018 08:32:24 +0100 Subject: [PATCH 2/2] remove django from install_requires as we can get this from wagtail dep --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 15737551..0f1678af 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,6 @@ install_requires = [ - 'Django>=2,<2.1', 'wagtail>=2,<2.2' ]