mirror of
https://github.com/wagtail/wagtail.git
synced 2024-12-01 11:41:20 +01:00
implement __setitem__ on StreamValue
This commit is contained in:
parent
603dc650e5
commit
caade5f0de
@ -1,7 +1,7 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from collections import OrderedDict, defaultdict
|
from collections import OrderedDict, defaultdict
|
||||||
from collections.abc import Sequence
|
from collections.abc import MutableSequence
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
|
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
|
||||||
@ -383,7 +383,7 @@ class StreamBlock(BaseStreamBlock, metaclass=DeclarativeSubBlocksMetaclass):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class StreamValue(Sequence):
|
class StreamValue(MutableSequence):
|
||||||
"""
|
"""
|
||||||
Custom type used to represent the value of a StreamBlock; behaves as a sequence of BoundBlocks
|
Custom type used to represent the value of a StreamBlock; behaves as a sequence of BoundBlocks
|
||||||
(which keep track of block types in a way that the values alone wouldn't).
|
(which keep track of block types in a way that the values alone wouldn't).
|
||||||
@ -446,16 +446,27 @@ class StreamValue(Sequence):
|
|||||||
else:
|
else:
|
||||||
# store native stream data in _bound_blocks; on serialization it will be converted to
|
# store native stream data in _bound_blocks; on serialization it will be converted to
|
||||||
# a JSON-ish representation via block.get_prep_value.
|
# a JSON-ish representation via block.get_prep_value.
|
||||||
self._bound_blocks = {}
|
self._bound_blocks = {
|
||||||
for i, item in enumerate(stream_data):
|
i: self._construct_stream_child(item)
|
||||||
try:
|
for i, item in enumerate(stream_data)
|
||||||
type_name, value, block_id = item
|
}
|
||||||
except ValueError:
|
|
||||||
type_name, value = item
|
|
||||||
block_id = None
|
|
||||||
|
|
||||||
block_def = self.stream_block.child_blocks[type_name]
|
def _construct_stream_child(self, item):
|
||||||
self._bound_blocks[i] = StreamValue.StreamChild(block_def, value, id=block_id)
|
"""
|
||||||
|
Create a StreamChild instance from a (type, value, id) or (type, value) tuple,
|
||||||
|
or return item if it's already a StreamChild
|
||||||
|
"""
|
||||||
|
if isinstance(item, StreamValue.StreamChild):
|
||||||
|
return item
|
||||||
|
|
||||||
|
try:
|
||||||
|
type_name, value, block_id = item
|
||||||
|
except ValueError:
|
||||||
|
type_name, value = item
|
||||||
|
block_id = None
|
||||||
|
|
||||||
|
block_def = self.stream_block.child_blocks[type_name]
|
||||||
|
return StreamValue.StreamChild(block_def, value, id=block_id)
|
||||||
|
|
||||||
def __getitem__(self, i):
|
def __getitem__(self, i):
|
||||||
if i not in range(0, self._length):
|
if i not in range(0, self._length):
|
||||||
@ -467,6 +478,15 @@ class StreamValue(Sequence):
|
|||||||
|
|
||||||
return self._bound_blocks[i]
|
return self._bound_blocks[i]
|
||||||
|
|
||||||
|
def __setitem__(self, i, item):
|
||||||
|
self._bound_blocks[i] = self._construct_stream_child(item)
|
||||||
|
|
||||||
|
def __delitem__(self, i):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def insert(self, i, item):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def _prefetch_blocks(self, type_name):
|
def _prefetch_blocks(self, type_name):
|
||||||
"""
|
"""
|
||||||
Populate _bound_blocks with all items in this stream of type `type_name` that exist in
|
Populate _bound_blocks with all items in this stream of type `type_name` that exist in
|
||||||
|
@ -3367,6 +3367,40 @@ class TestStreamBlock(WagtailTestUtils, SimpleTestCase):
|
|||||||
{'type': 'paragraph', 'value': 'earth', 'id': '0002'},
|
{'type': 'paragraph', 'value': 'earth', 'id': '0002'},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_set_streamvalue_item(self):
|
||||||
|
class ArticleBlock(blocks.StreamBlock):
|
||||||
|
heading = blocks.CharBlock()
|
||||||
|
paragraph = blocks.CharBlock()
|
||||||
|
|
||||||
|
block = ArticleBlock()
|
||||||
|
stream = block.to_python([
|
||||||
|
{'type': 'heading', 'value': 'hello', 'id': '0001'},
|
||||||
|
{'type': 'paragraph', 'value': 'world', 'id': '0002'},
|
||||||
|
])
|
||||||
|
stream[1] = ('heading', 'goodbye', '0003')
|
||||||
|
raw_data = block.get_prep_value(stream)
|
||||||
|
self.assertEqual(raw_data, [
|
||||||
|
{'type': 'heading', 'value': 'hello', 'id': '0001'},
|
||||||
|
{'type': 'heading', 'value': 'goodbye', 'id': '0003'},
|
||||||
|
])
|
||||||
|
|
||||||
|
@unittest.expectedFailure
|
||||||
|
def test_delete_streamvalue_item(self):
|
||||||
|
class ArticleBlock(blocks.StreamBlock):
|
||||||
|
heading = blocks.CharBlock()
|
||||||
|
paragraph = blocks.CharBlock()
|
||||||
|
|
||||||
|
block = ArticleBlock()
|
||||||
|
stream = block.to_python([
|
||||||
|
{'type': 'heading', 'value': 'hello', 'id': '0001'},
|
||||||
|
{'type': 'paragraph', 'value': 'world', 'id': '0002'},
|
||||||
|
])
|
||||||
|
del stream[0]
|
||||||
|
raw_data = block.get_prep_value(stream)
|
||||||
|
self.assertEqual(raw_data, [
|
||||||
|
{'type': 'paragraph', 'value': 'world', 'id': '0002'},
|
||||||
|
])
|
||||||
|
|
||||||
def test_render_with_classname_via_kwarg(self):
|
def test_render_with_classname_via_kwarg(self):
|
||||||
"""form_classname from kwargs to be used as an additional class when rendering stream block"""
|
"""form_classname from kwargs to be used as an additional class when rendering stream block"""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user