如何渲染 StreamField 的单个子块?
How might one render an individual sub-Block of a StreamField?
我有一个难题,希望 Wagtail 内部专家可以帮助我解决。我最终要做的是将一个复杂的、嵌套的基于 StreamField 的页面呈现为 plaintext/HTML,可用于搜索索引并在搜索结果页面上显示为片段。
问题是页面上的某些块 不应 包含在搜索索引中,因为它们包含有关其他(大部分不相关)页面的元数据。所以我不希望搜索页面 A 得到仅引用页面 A 的结果。
我想出的解决方案是手动遍历块树,只渲染 StreamField 中的某些类型的块。但是,虽然这对于 RichTextBlock
来说相对容易,因为我可以从块字典中提取 'value' 字符串,但对于我们的任何自定义块来说,这并不简单。
我想为单个块渲染 HTML,但我真的不确定该怎么做,如果这样的事情可能的话。在深入研究 StreamField 的渲染管道之后,我最好的引导是我可以使用适当的数据手动构建 BoundBlock
,然后在其上调用 render()
。但我不太确定如何获取原始块字典并将其转换为 StreamValue
以便从中构建 BoundBlock
。如果这是正确的想法...
我也在研究一个反向解决方案,以防我在这里吠叫错误的树。我想我可以将一个特定的上下文变量传递给生成搜索索引的函数中的 StreamField.render_as_block(context)
,我可以对要查找的各个块进行编程,然后如果它们看到则根本不渲染它们自己它。如果我设法解决这个问题,我会更新这个问题。
不知道我理解的对不对,你可以遍历StreamField的块。一些例子:
块定义:
class MyCustomImageBlock(StructBlock):
image = ImageChooserBlock()
caption = CharBlock()
class Meta:
template = '/blocks/image-with-caption.html'
icon = 'image'
class MyCarouselBlock(ListBlock):
class Meta:
template = '/blocks/custom-list.html'
icon = 'media'
ImageWithCaptionblock
自定义 StreamBlock 定义:
class MyCustomStreamBlock(StreamBlock):
some_image = MyCustomImageBlock()
image_carousel = MyCarouselBlock(child_block=MyCustomImageBlock)
页面定义:
class MyPage(Page):
content = StreamField(MyCustomStreamBlock())
模板
现在您可以简单地渲染 StreamField 的块,并使用 include_block 来渲染各个块。你也可以传递变量。
{% for block in page.content %}
{% include_block block with current_page=page %} # in case you want to render only something when on a certain page
{% endfor %}
我经常使用的一些技巧是:
创建一个自定义 StreamBlock,它只包含一种类型的自定义块。然后循环一些变量以呈现内容编辑器为每个块使用不同样式定义的数据:
{% for block in page.content %}
<!--
{% cycle 'right' 'left' as position %}
{% cycle 'primary' 'secondary' 'white' as color %}
-->
{% include_block block with pos=position color=color %}
{% endfor %}
我有一个难题,希望 Wagtail 内部专家可以帮助我解决。我最终要做的是将一个复杂的、嵌套的基于 StreamField 的页面呈现为 plaintext/HTML,可用于搜索索引并在搜索结果页面上显示为片段。
问题是页面上的某些块 不应 包含在搜索索引中,因为它们包含有关其他(大部分不相关)页面的元数据。所以我不希望搜索页面 A 得到仅引用页面 A 的结果。
我想出的解决方案是手动遍历块树,只渲染 StreamField 中的某些类型的块。但是,虽然这对于 RichTextBlock
来说相对容易,因为我可以从块字典中提取 'value' 字符串,但对于我们的任何自定义块来说,这并不简单。
我想为单个块渲染 HTML,但我真的不确定该怎么做,如果这样的事情可能的话。在深入研究 StreamField 的渲染管道之后,我最好的引导是我可以使用适当的数据手动构建 BoundBlock
,然后在其上调用 render()
。但我不太确定如何获取原始块字典并将其转换为 StreamValue
以便从中构建 BoundBlock
。如果这是正确的想法...
我也在研究一个反向解决方案,以防我在这里吠叫错误的树。我想我可以将一个特定的上下文变量传递给生成搜索索引的函数中的 StreamField.render_as_block(context)
,我可以对要查找的各个块进行编程,然后如果它们看到则根本不渲染它们自己它。如果我设法解决这个问题,我会更新这个问题。
不知道我理解的对不对,你可以遍历StreamField的块。一些例子:
块定义:
class MyCustomImageBlock(StructBlock):
image = ImageChooserBlock()
caption = CharBlock()
class Meta:
template = '/blocks/image-with-caption.html'
icon = 'image'
class MyCarouselBlock(ListBlock):
class Meta:
template = '/blocks/custom-list.html'
icon = 'media'
ImageWithCaptionblock
自定义 StreamBlock 定义:
class MyCustomStreamBlock(StreamBlock):
some_image = MyCustomImageBlock()
image_carousel = MyCarouselBlock(child_block=MyCustomImageBlock)
页面定义:
class MyPage(Page):
content = StreamField(MyCustomStreamBlock())
模板
现在您可以简单地渲染 StreamField 的块,并使用 include_block 来渲染各个块。你也可以传递变量。
{% for block in page.content %}
{% include_block block with current_page=page %} # in case you want to render only something when on a certain page
{% endfor %}
我经常使用的一些技巧是: 创建一个自定义 StreamBlock,它只包含一种类型的自定义块。然后循环一些变量以呈现内容编辑器为每个块使用不同样式定义的数据:
{% for block in page.content %}
<!--
{% cycle 'right' 'left' as position %}
{% cycle 'primary' 'secondary' 'white' as color %}
-->
{% include_block block with pos=position color=color %}
{% endfor %}