我有一个难题,希望Wagtail内部专家可以帮助我解决。我最终想要做的是将一个复杂的,嵌套的基于StreamField的页面呈现为纯文本/ HTML,可用于搜索索引和在搜索结果页面上显示为代码段。
问题是页面上的某些块不应 包含在搜索索引中,因为它们包含有关其他大部分不相关页面的元数据。因此,我不想搜索页面A来显示仅引用页面A的结果。
我想出的解决方案是手动遍历块树,仅在StreamField中渲染某些类型的块。但是,尽管这对于RichTextBlock
来说相对来说比较容易,但是由于我可以将“ value”字符串从代码块字典中删除,因此对于我们的任何自定义代码块来说,这都不简单。
我想呈现单个块的HTML,但是我什至不知道如何做到这一点,即使有可能的话。在深入研究StreamField的渲染管道之后,我最好的线索是,我可以使用适当的数据手动构建一个BoundBlock
,然后在其上调用render()
。但是我不确定如何将原始的dict变成StreamValue
以便构建BoundBlock
。如果那是正确的主意...
我也在研究一种反向解决方案,以防万一我在这里树错了树。我认为我可以在生成搜索索引的函数中将特定的上下文变量传递到StreamField.render_as_block(context)
中,可以对单个块进行编程以查找它们,然后在看到时完全不渲染自己。它。如果我设法解决该问题,我将更新此问题。
答案 0 :(得分:2)
我不知道我是否理解正确,但是您可以遍历StreamField的块。一些例子:
块定义:
select c.name,
(case when max(e.time) > NOW() then 'Yes' else 'No' end) AS "time"
from table1 e join
table2 a
on e.id = a.id join
table3 c
on a.id = c.id
where e.name = 'JOHN'
group by c.name;
ImageWithCaptionblock
自定义StreamBlock定义:
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'
页面定义:
class MyCustomStreamBlock(StreamBlock):
some_image = MyCustomImageBlock()
image_carousel = MyCarouselBlock(child_block=MyCustomImageBlock)
模板
现在,您可以简单地在StreamField的块上进行渲染,并使用include_block来渲染各个块。您也可以传递变量。
class MyPage(Page):
content = StreamField(MyCustomStreamBlock())
我经常使用的一些技巧是: 创建一个仅包含一种类型的自定义块的自定义StreamBlock。然后循环一些变量以呈现内容编辑器为每个块定义的样式不同的数据:
{% 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 %}