有没有比这更好的方法来制作ListBlock
具有固定内容的子类?
class MixedMediaCarouselBlock(blocks.ListBlock):
"""
A hghly streamlined CarouselBlock which displays only Images and/or Videos.
"""
def __init__(self, child_block=None, **kwargs):
child_block = blocks.StructBlock([
('image', ImageChooserBlock(required=False)),
('video', EmbedBlock(
label="Video URL",
help_text="Paste the video URL from YouTube or Vimeo."
" e.g. https://www.youtube.com/watch?v=l3Pz_xQZVDg"
" or https://vimeo.com/207076450.",
required=False
)
),
])
super(MixedMediaCarouselBlock, self).__init__(child_block, **kwargs)
class Meta:
template = 'core/blocks/mixed_media_carousel_block.html'
label = 'Mixed Media Carousel'
icon = 'media'
这样做感觉真的很糟糕,但我找不到任何其他明显的方法,因为它的构造函数ListBlock
需要该child_block
参数,而其他块类型则不需要。
我想要一个ListBlock
子类的原因是将它用作我的一个页面中的单个块类型StreamField
:
class News(Page)
assets = StreamField(
MixedMediaCarouselBlock(),
help_text='Pick one or more images/videos to place in the sidebar of this article.'
)
也许我只是做错了?
编辑:是的,我肯定做错了什么。这根本不起作用,因为当我尝试使用此设置保存页面并进入AttributeError: 'MixedMediaCarouselBlock' object has no attribute 'child_blocks'
wagtail/wagtailcore/blocks/stream_block.py 第 401 行时才发现。(Wagtail 1.12.2)。不过不知道为什么。
EDIT2:我听从@gasman 的建议,想出了这个:
class MixedMediaCarouselBlock(blocks.StreamBlock):
slides = blocks.ListBlock(
blocks.StructBlock([
('image', ImageChooserBlock(required=False)),
('video', EmbedBlock(
label="Video URL",
help_text="Paste the video URL from YouTube or Vimeo."
" e.g. https://www.youtube.com/watch?v=l3Pz_xQZVDg or https://vimeo.com/207076450.",
required=False
)
),
])
)
但我仍然在页面编辑表单上得到一个块类型菜单(我正在使用 wagtail-facelift):
更糟糕的是,表单允许我slides
向 StreamField 添加多个实例,这很容易导致用户不小心制作了多个单元素 ListBlock,而不是一个多元素 ListBlock,这会破坏渲染器。我能做些什么呢?
EDIT3:这是我经过大量实验后想出的,但我一点也不喜欢它。
class MixedMediaCarouselBlock(blocks.StructBlock):
"""
A hghly streamlined CarouselBlock which displays only Images and/or Videos.
"""
slides = blocks.ListBlock(
blocks.StructBlock([
('image', ImageChooserBlock(required=False)),
('video', EmbedBlock(
label="Video URL",
help_text="Paste the video URL from YouTube or Vimeo."
" e.g. https://www.youtube.com/watch?v=l3Pz_xQZVDg or https://vimeo.com/207076450.",
required=False
)
),
])
)
class Meta:
template = 'core/blocks/mixed_media_carousel_block.html'
label = 'Mixed Media Carousel'
icon = 'media'
class News(Page):
...
assets = StreamField(
('media', MixedMediaCarouselBlock()),
help_text='Pick one or more images/videos to place in the sidebar of this article.'
)
然后,为了解决用户在单个 s 中意外添加多个MixedMediaCarouselBlock
s 而不是多个视频/图像的问题MixedMediaCarouselBlock
,我修改了一些 LESS CSS 来隐藏允许他们这样做的 UI:
body.model-news {
.stream-menu .toggle {
display: none;
}
.sequence-controls:not(.list-controls) button[id$=delete] {
display: none;
}
}
在我的研发过程中,我遇到了 Wagtail 1.12 补丁说明,其中提到将min_num
、max_num
和block_counts
元属性添加到StreamBlock
,这听起来很有希望。但它们不会影响 UI;他们只是添加了服务器端验证,使无效的选择在 POST 后显示为表单错误。如果他们一开始就阻止了无效的更改,我实际上可以使用它们。