kopia lustrzana https://github.com/wagtail/wagtail
rodzic
bdfa3811d1
commit
8c97c254a7
|
@ -440,9 +440,11 @@ Structural block types
|
|||
]))),
|
||||
])
|
||||
|
||||
The following additional option is available as either a keyword argument or a Meta class attribute:
|
||||
The following additional options are available as either keyword arguments or Meta class attributes:
|
||||
|
||||
:param form_classname: An HTML ``class`` attribute to set on the root element of this block as displayed in the editing interface.
|
||||
:param min_num: Minimum number of sub-blocks that the list must have.
|
||||
:param max_num: Maximum number of sub-blocks that the list may have.
|
||||
|
||||
|
||||
.. class:: wagtail.core.blocks.StreamBlock
|
||||
|
|
|
@ -98,6 +98,16 @@ class ListBlock(Block):
|
|||
else:
|
||||
errors.append(None)
|
||||
|
||||
if self.meta.min_num is not None and self.meta.min_num > len(value):
|
||||
non_block_errors.append(ValidationError(
|
||||
_('The minimum number of items is %d') % self.meta.min_num
|
||||
))
|
||||
|
||||
if self.meta.max_num is not None and self.meta.max_num < len(value):
|
||||
non_block_errors.append(ValidationError(
|
||||
_('The maximum number of items is %d') % self.meta.max_num
|
||||
))
|
||||
|
||||
if any(errors) or non_block_errors:
|
||||
raise ListBlockValidationError(block_errors=errors, non_block_errors=non_block_errors)
|
||||
|
||||
|
@ -172,6 +182,10 @@ class ListBlock(Block):
|
|||
# descendant block type
|
||||
icon = "placeholder"
|
||||
form_classname = None
|
||||
min_num = None
|
||||
max_num = None
|
||||
|
||||
MUTABLE_META_ATTRIBUTES = ['min_num', 'max_num']
|
||||
|
||||
|
||||
class ListBlockAdapter(Adapter):
|
||||
|
@ -193,6 +207,12 @@ class ListBlockAdapter(Adapter):
|
|||
meta['helpText'] = help_text
|
||||
meta['helpIcon'] = get_help_icon()
|
||||
|
||||
if block.meta.min_num is not None:
|
||||
meta['minNum'] = block.meta.min_num
|
||||
|
||||
if block.meta.max_num is not None:
|
||||
meta['maxNum'] = block.meta.max_num
|
||||
|
||||
return [
|
||||
block.name,
|
||||
block.child_block,
|
||||
|
|
|
@ -2179,6 +2179,34 @@ class TestListBlock(WagtailTestUtils, SimpleTestCase):
|
|||
},
|
||||
})
|
||||
|
||||
def test_adapt_with_min_num_max_num(self):
|
||||
class LinkBlock(blocks.StructBlock):
|
||||
title = blocks.CharBlock()
|
||||
link = blocks.URLBlock()
|
||||
|
||||
block = blocks.ListBlock(LinkBlock, min_num=2, max_num=5)
|
||||
|
||||
block.set_name('test_listblock')
|
||||
js_args = ListBlockAdapter().js_args(block)
|
||||
|
||||
self.assertEqual(js_args[0], 'test_listblock')
|
||||
self.assertIsInstance(js_args[1], LinkBlock)
|
||||
self.assertEqual(js_args[2], {'title': None, 'link': None})
|
||||
self.assertEqual(js_args[3], {
|
||||
'label': 'Test listblock',
|
||||
'icon': 'placeholder',
|
||||
'classname': None,
|
||||
'minNum': 2,
|
||||
'maxNum': 5,
|
||||
'strings': {
|
||||
'DELETE': 'Delete',
|
||||
'DUPLICATE': 'Duplicate',
|
||||
'MOVE_DOWN': 'Move down',
|
||||
'MOVE_UP': 'Move up',
|
||||
'ADD': 'Add',
|
||||
},
|
||||
})
|
||||
|
||||
def test_searchable_content(self):
|
||||
class LinkBlock(blocks.StructBlock):
|
||||
title = blocks.CharBlock()
|
||||
|
@ -2332,6 +2360,32 @@ class TestListBlock(WagtailTestUtils, SimpleTestCase):
|
|||
},
|
||||
})
|
||||
|
||||
def test_min_num_validation_errors(self):
|
||||
block = blocks.ListBlock(blocks.CharBlock(), min_num=2)
|
||||
|
||||
with self.assertRaises(ValidationError) as catcher:
|
||||
block.clean(['foo'])
|
||||
self.assertEqual(catcher.exception.params, {
|
||||
'block_errors': [None],
|
||||
'non_block_errors': ['The minimum number of items is 2']
|
||||
})
|
||||
|
||||
# a value with >= 2 blocks should pass validation
|
||||
self.assertTrue(block.clean(['foo', 'bar']))
|
||||
|
||||
def test_max_num_validation_errors(self):
|
||||
block = blocks.ListBlock(blocks.CharBlock(), max_num=2)
|
||||
|
||||
with self.assertRaises(ValidationError) as catcher:
|
||||
block.clean(['foo', 'bar', 'baz'])
|
||||
self.assertEqual(catcher.exception.params, {
|
||||
'block_errors': [None, None, None],
|
||||
'non_block_errors': ['The maximum number of items is 2']
|
||||
})
|
||||
|
||||
# a value with <= 2 blocks should pass validation
|
||||
self.assertTrue(block.clean(['foo', 'bar']))
|
||||
|
||||
|
||||
class TestListBlockWithFixtures(TestCase):
|
||||
fixtures = ['test.json']
|
||||
|
|
Ładowanie…
Reference in New Issue