Browse Source

Remove use_json_field parameter from StreamField

Matt Westcott 1 year ago
parent
commit
c49ec1bb06

+ 1 - 1
docs/advanced_topics/boundblocks_and_values.md

@@ -24,7 +24,7 @@ class BlogPage(Page):
         # ...
         ('heading', HeadingBlock()),
         # ...
-    ], use_json_field=True)
+    ])
 ```
 
 ```html+django

+ 0 - 2
docs/advanced_topics/streamfield_migrations.md

@@ -59,7 +59,6 @@ class Migration(migrations.Migration):
             name="body",
             field=wagtail.fields.StreamField(
                 [("rich_text", wagtail.blocks.RichTextBlock())],
-                use_json_field=True,
             ),
         ),
     ]
@@ -200,7 +199,6 @@ class Migration(migrations.Migration):
             name="body",
             field=wagtail.fields.StreamField(
                 [("rich_text", wagtail.blocks.RichTextBlock())],
-                use_json_field=True,
             ),
         ),
     ]

+ 14 - 10
docs/reference/streamfield/blocks.md

@@ -9,12 +9,11 @@ This document details the block types provided by Wagtail for use in [StreamFiel
 ```
 
 ```{eval-rst}
-.. class:: wagtail.fields.StreamField(blocks, use_json_field=None, blank=False, min_num=None, max_num=None, block_counts=None, collapsed=False)
+.. class:: wagtail.fields.StreamField(blocks, blank=False, min_num=None, max_num=None, block_counts=None, collapsed=False)
 
    A model field for representing long-form content as a sequence of content blocks of various types. See :ref:`streamfield_topic`.
 
    :param blocks: A list of block types, passed as either a list of ``(name, block_definition)`` tuples or a ``StreamBlock`` instance.
-   :param use_json_field: Must be set to ``True``. This causes the field to use :class:`~django.db.models.JSONField` as its internal type, allowing the use of ``JSONField`` lookups and transforms.
    :param blank: When false (the default), at least one block must be provided for the field to be considered valid.
    :param min_num: Minimum number of sub-blocks that the stream must have.
    :param max_num: Maximum number of sub-blocks that the stream may have.
@@ -30,9 +29,15 @@ body = StreamField([
 ], block_counts={
     'heading': {'min_num': 1},
     'image': {'max_num': 5},
-}, use_json_field=True)
+})
 ```
 
+```{versionchanged} 6.0
+
+The `use_json_field` argument is no longer required.
+```
+
+
 ## Block options
 
 All block definitions accept the following optional keyword arguments:
@@ -414,7 +419,7 @@ All block definitions accept the following optional keyword arguments:
                ('photo', ImageChooserBlock(required=False)),
                ('biography', blocks.RichTextBlock()),
            ], icon='user')),
-       ], use_json_field=True)
+       ])
 
 
     Alternatively, StructBlock can be subclassed to specify a reusable set of sub-blocks:
@@ -443,7 +448,7 @@ All block definitions accept the following optional keyword arguments:
            ('paragraph', blocks.RichTextBlock()),
            ('image', ImageChooserBlock()),
            ('person', PersonBlock()),
-       ], use_json_field=True)
+       ])
 
 
     The following additional options are available as either keyword arguments or Meta class attributes:
@@ -466,7 +471,7 @@ All block definitions accept the following optional keyword arguments:
        body = StreamField([
            # ...
            ('ingredients_list', blocks.ListBlock(blocks.CharBlock(label="Ingredient"))),
-       ], use_json_field=True)
+       ])
 
 
 
@@ -480,7 +485,7 @@ All block definitions accept the following optional keyword arguments:
                ('ingredient', blocks.CharBlock()),
                ('amount', blocks.CharBlock(required=False)),
            ]))),
-       ], use_json_field=True)
+       ])
 
 
     The following additional options are available as either keyword arguments or Meta class attributes:
@@ -512,7 +517,7 @@ All block definitions accept the following optional keyword arguments:
                ],
                icon='cogs'
            )),
-       ], use_json_field=True)
+       ])
 
 
     As with StructBlock, the list of sub-blocks can also be provided as a subclass of StreamBlock:
@@ -537,7 +542,6 @@ All block definitions accept the following optional keyword arguments:
         class HomePage(Page):
             carousel = StreamField(
                 CarouselBlock(max_num=10, block_counts={'video': {'max_num': 2}}),
-                use_json_field=True
             )
 
     ``StreamBlock`` accepts the following additional options as either keyword arguments or ``Meta`` properties:
@@ -559,7 +563,7 @@ All block definitions accept the following optional keyword arguments:
                 ('hashtag', blocks.CharBlock()),
                 ('post_date', blocks.DateBlock()),
             ], form_classname='event-promotions')),
-        ], use_json_field=True)
+        ])
 
     .. code-block:: python
         :emphasize-lines: 6

+ 9 - 9
docs/topics/streamfield.md

@@ -28,7 +28,7 @@ class BlogPage(Page):
         ('heading', blocks.CharBlock(form_classname="title")),
         ('paragraph', blocks.RichTextBlock()),
         ('image', ImageChooserBlock()),
-    ], use_json_field=True)
+    ])
 
     content_panels = Page.content_panels + [
         FieldPanel('author'),
@@ -124,7 +124,7 @@ body = StreamField([
     ('heading', blocks.CharBlock(form_classname="title")),
     ('paragraph', blocks.RichTextBlock()),
     ('image', ImageChooserBlock()),
-], use_json_field=True)
+])
 ```
 
 When reading back the content of a StreamField (such as when rendering a template), the value of a StructBlock is a dict-like object with keys corresponding to the block names given in the definition:
@@ -165,7 +165,7 @@ body = StreamField([
     ('heading', blocks.CharBlock(form_classname="title")),
     ('paragraph', blocks.RichTextBlock()),
     ('image', ImageChooserBlock()),
-], use_json_field=True)
+])
 ```
 
 ### Block icons
@@ -185,7 +185,7 @@ body = StreamField([
     ('heading', blocks.CharBlock(form_classname="title")),
     ('paragraph', blocks.RichTextBlock()),
     ('image', ImageChooserBlock()),
-], use_json_field=True)
+])
 ```
 
 ```{code-block} python
@@ -215,7 +215,7 @@ body = StreamField([
     ('heading', blocks.CharBlock(form_classname="title")),
     ('paragraph', blocks.RichTextBlock()),
     ('image', ImageChooserBlock()),
-], use_json_field=True)
+])
 ```
 
 When reading back the content of a StreamField (such as when rendering a template), the value of a ListBlock is a list of child values:
@@ -251,7 +251,7 @@ body = StreamField([
     ('heading', blocks.CharBlock(form_classname="title")),
     ('paragraph', blocks.RichTextBlock()),
     ('image', ImageChooserBlock()),
-], use_json_field=True)
+])
 ```
 
 `StreamBlock` can also be subclassed in the same way as `StructBlock`, with the child blocks being specified as attributes on the class:
@@ -275,7 +275,7 @@ class CommonContentBlock(blocks.StreamBlock):
 
 
 class BlogPage(Page):
-    body = StreamField(CommonContentBlock(), use_json_field=True)
+    body = StreamField(CommonContentBlock())
 ```
 
 When reading back the content of a StreamField, the value of a StreamBlock is a sequence of block objects with `block_type` and `value` properties, just like the top-level value of the StreamField itself.
@@ -309,7 +309,7 @@ body = StreamField([
     ('heading', blocks.CharBlock(form_classname="title")),
     ('paragraph', blocks.RichTextBlock()),
     ('image', ImageChooserBlock()),
-], min_num=2, max_num=5, use_json_field=True)
+], min_num=2, max_num=5)
 ```
 
 Or equivalently:
@@ -334,7 +334,7 @@ body = StreamField([
     ('image', ImageChooserBlock()),
 ], block_counts={
     'heading': {'min_num': 1, 'max_num': 3},
-}, use_json_field=True)
+})
 ```
 
 Or equivalently:

+ 4 - 17
wagtail/fields.py

@@ -1,6 +1,5 @@
 import json
 
-from django.core.exceptions import ImproperlyConfigured
 from django.core.serializers.json import DjangoJSONEncoder
 from django.core.validators import MaxLengthValidator
 from django.db import models
@@ -83,7 +82,10 @@ class Creator:
 
 
 class StreamField(models.Field):
-    def __init__(self, block_types, use_json_field=None, **kwargs):
+    def __init__(self, block_types, use_json_field=True, **kwargs):
+        # use_json_field no longer has any effect but is recognised to support historical
+        # migrations
+
         # extract kwargs that are to be passed on to the block, not handled by super
         block_opts = {}
         for arg in ["min_num", "max_num", "block_counts", "collapsed"]:
@@ -97,8 +99,6 @@ class StreamField(models.Field):
 
         super().__init__(**kwargs)
 
-        self.use_json_field = use_json_field
-
         if isinstance(block_types, Block):
             # use the passed block as the top-level block
             self.stream_block = block_types
@@ -115,13 +115,6 @@ class StreamField(models.Field):
     def json_field(self):
         return models.JSONField(encoder=DjangoJSONEncoder)
 
-    def _check_json_field(self):
-        if self.use_json_field is not True:
-            # RemovedInWagtail60Warning - make use_json_field optional and default to True
-            raise ImproperlyConfigured(
-                "StreamField must explicitly set use_json_field=True"
-            )
-
     def get_internal_type(self):
         return "JSONField"
 
@@ -135,7 +128,6 @@ class StreamField(models.Field):
         name, path, _, kwargs = super().deconstruct()
         block_types = list(self.stream_block.child_blocks.items())
         args = [block_types]
-        kwargs["use_json_field"] = self.use_json_field
         return name, path, args, kwargs
 
     def to_python(self, value):
@@ -273,11 +265,6 @@ class StreamField(models.Field):
     def contribute_to_class(self, cls, name, **kwargs):
         super().contribute_to_class(cls, name, **kwargs)
 
-        # Output error on missing use_json_field=True argument, unless this is a fake model
-        # for a migration
-        if cls.__module__ != "__fake__":
-            self._check_json_field()
-
         # Add Creator descriptor to allow the field to be set from a list or a
         # JSON string.
         setattr(cls, self.name, Creator(self))

+ 2 - 2
wagtail/test/streamfield_migrations/models.py

@@ -42,8 +42,8 @@ class BaseStreamBlock(StreamBlock):
 
 
 class SampleModel(models.Model):
-    content = StreamField(BaseStreamBlock(), use_json_field=True)
+    content = StreamField(BaseStreamBlock())
 
 
 class SamplePage(Page):
-    content = StreamField(BaseStreamBlock(), use_json_field=True)
+    content = StreamField(BaseStreamBlock())

+ 4 - 14
wagtail/test/testapp/models.py

@@ -1241,7 +1241,6 @@ class VariousOnDeleteModel(models.Model):
             ("image", ImageChooserBlock()),
             ("document", DocumentChooserBlock()),
         ],
-        use_json_field=True,
     )
     rich_text = RichTextField(blank=True)
 
@@ -1451,7 +1450,6 @@ class JSONStreamModel(models.Model):
             ("rich_text", RichTextBlock()),
             ("image", ImageChooserBlock()),
         ],
-        use_json_field=True,
     )
 
 
@@ -1464,7 +1462,6 @@ class JSONMinMaxCountStreamModel(models.Model):
         ],
         min_num=2,
         max_num=5,
-        use_json_field=True,
     )
 
 
@@ -1480,7 +1477,6 @@ class JSONBlockCountsStreamModel(models.Model):
             "rich_text": {"max_num": 1},
             "image": {"min_num": 1, "max_num": 1},
         },
-        use_json_field=True,
     )
 
 
@@ -1530,7 +1526,6 @@ class StreamPage(Page):
                 ListBlock(CharBlock()),
             ),
         ],
-        use_json_field=True,
     )
 
     api_fields = ("body",)
@@ -1551,7 +1546,6 @@ class DefaultStreamPage(Page):
             ("image", ImageChooserBlock()),
         ],
         default="",
-        use_json_field=True,
     )
 
     content_panels = [
@@ -1789,7 +1783,6 @@ class DefaultRichBlockFieldPage(Page):
         [
             ("rich_text", RichTextBlock()),
         ],
-        use_json_field=True,
     )
 
     content_panels = Page.content_panels + [FieldPanel("body")]
@@ -1809,7 +1802,6 @@ class CustomRichBlockFieldPage(Page):
         [
             ("rich_text", RichTextBlock(editor="custom")),
         ],
-        use_json_field=True,
     )
 
     content_panels = [
@@ -1855,7 +1847,6 @@ class InlineStreamPageSection(Orderable):
             ("rich_text", RichTextBlock()),
             ("image", ImageChooserBlock()),
         ],
-        use_json_field=True,
     )
     panels = [FieldPanel("body")]
 
@@ -1868,7 +1859,7 @@ class InlineStreamPage(Page):
 
 
 class TableBlockStreamPage(Page):
-    table = StreamField([("table", TableBlock())], use_json_field=True)
+    table = StreamField([("table", TableBlock())])
 
     content_panels = [FieldPanel("table")]
 
@@ -1911,15 +1902,15 @@ class AlwaysShowInMenusPage(Page):
 
 # test for AddField migrations on StreamFields using various default values
 class AddedStreamFieldWithoutDefaultPage(Page):
-    body = StreamField([("title", CharBlock())], use_json_field=True)
+    body = StreamField([("title", CharBlock())])
 
 
 class AddedStreamFieldWithEmptyStringDefaultPage(Page):
-    body = StreamField([("title", CharBlock())], default="", use_json_field=True)
+    body = StreamField([("title", CharBlock())], default="")
 
 
 class AddedStreamFieldWithEmptyListDefaultPage(Page):
-    body = StreamField([("title", CharBlock())], default=[], use_json_field=True)
+    body = StreamField([("title", CharBlock())], default=[])
 
 
 class SecretPage(Page):
@@ -2047,7 +2038,6 @@ class DeadlyStreamPage(Page):
         [
             ("title", DeadlyCharBlock()),
         ],
-        use_json_field=True,
     )
     content_panels = Page.content_panels + [
         FieldPanel("body"),

+ 11 - 19
wagtail/tests/test_streamfield.py

@@ -198,7 +198,6 @@ class TestSystemCheck(TestCase):
                     ("heading", blocks.CharBlock()),
                     ("rich text", blocks.RichTextBlock()),
                 ],
-                use_json_field=True,
             )
 
         errors = InvalidStreamModel.check()
@@ -308,7 +307,6 @@ class TestRequiredStreamField(TestCase):
         field = StreamField(
             [("paragraph", blocks.CharBlock())],
             blank=False,
-            use_json_field=True,
         )
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
@@ -321,7 +319,7 @@ class TestRequiredStreamField(TestCase):
                 required = False
 
         # passing a block instance
-        field = StreamField(MyStreamBlock(), blank=False, use_json_field=True)
+        field = StreamField(MyStreamBlock(), blank=False)
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
             field.stream_block.clean([])
@@ -329,21 +327,20 @@ class TestRequiredStreamField(TestCase):
         field = StreamField(
             MyStreamBlock(required=False),
             blank=False,
-            use_json_field=True,
         )
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
             field.stream_block.clean([])
 
         # passing a block class
-        field = StreamField(MyStreamBlock, blank=False, use_json_field=True)
+        field = StreamField(MyStreamBlock, blank=False)
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
             field.stream_block.clean([])
 
     def test_blank_false_is_implied_by_default(self):
         # passing a block list
-        field = StreamField([("paragraph", blocks.CharBlock())], use_json_field=True)
+        field = StreamField([("paragraph", blocks.CharBlock())])
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
             field.stream_block.clean([])
@@ -355,18 +352,18 @@ class TestRequiredStreamField(TestCase):
                 required = False
 
         # passing a block instance
-        field = StreamField(MyStreamBlock(), use_json_field=True)
+        field = StreamField(MyStreamBlock())
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
             field.stream_block.clean([])
 
-        field = StreamField(MyStreamBlock(required=False), use_json_field=True)
+        field = StreamField(MyStreamBlock(required=False))
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
             field.stream_block.clean([])
 
         # passing a block class
-        field = StreamField(MyStreamBlock, use_json_field=True)
+        field = StreamField(MyStreamBlock)
         self.assertTrue(field.stream_block.required)
         with self.assertRaises(StreamBlockValidationError):
             field.stream_block.clean([])
@@ -376,7 +373,6 @@ class TestRequiredStreamField(TestCase):
         field = StreamField(
             [("paragraph", blocks.CharBlock())],
             blank=True,
-            use_json_field=True,
         )
         self.assertFalse(field.stream_block.required)
         field.stream_block.clean([])  # no validation error on empty stream
@@ -388,18 +384,16 @@ class TestRequiredStreamField(TestCase):
                 required = True
 
         # passing a block instance
-        field = StreamField(MyStreamBlock(), blank=True, use_json_field=True)
+        field = StreamField(MyStreamBlock(), blank=True)
         self.assertFalse(field.stream_block.required)
         field.stream_block.clean([])  # no validation error on empty stream
 
-        field = StreamField(
-            MyStreamBlock(required=True), blank=True, use_json_field=True
-        )
+        field = StreamField(MyStreamBlock(required=True), blank=True)
         self.assertFalse(field.stream_block.required)
         field.stream_block.clean([])  # no validation error on empty stream
 
         # passing a block class
-        field = StreamField(MyStreamBlock, blank=True, use_json_field=True)
+        field = StreamField(MyStreamBlock, blank=True)
         self.assertFalse(field.stream_block.required)
         field.stream_block.clean([])  # no validation error on empty stream
 
@@ -536,7 +530,7 @@ class TestStreamFieldCountValidation(TestCase):
                 block_counts = {"heading": {"max_num": 1}}
 
         # args being picked up from the class definition
-        field = StreamField(TestStreamBlock, use_json_field=True)
+        field = StreamField(TestStreamBlock)
         self.assertEqual(field.stream_block.meta.min_num, 2)
         self.assertEqual(field.stream_block.meta.max_num, 5)
         self.assertEqual(field.stream_block.meta.block_counts["heading"]["max_num"], 1)
@@ -547,7 +541,6 @@ class TestStreamFieldCountValidation(TestCase):
             min_num=3,
             max_num=6,
             block_counts={"heading": {"max_num": 2}},
-            use_json_field=True,
         )
         self.assertEqual(field.stream_block.meta.min_num, 3)
         self.assertEqual(field.stream_block.meta.max_num, 6)
@@ -559,7 +552,6 @@ class TestStreamFieldCountValidation(TestCase):
             min_num=None,
             max_num=None,
             block_counts=None,
-            use_json_field=True,
         )
         self.assertIsNone(field.stream_block.meta.min_num)
         self.assertIsNone(field.stream_block.meta.max_num)
@@ -575,7 +567,7 @@ class TestJSONStreamField(TestCase):
         )
 
     def test_internal_type(self):
-        json = StreamField([("paragraph", blocks.CharBlock())], use_json_field=True)
+        json = StreamField([("paragraph", blocks.CharBlock())])
         self.assertEqual(json.get_internal_type(), "JSONField")
 
     def test_json_body_equals_to_text_body(self):