如何从 wagtail 块模板中的 struct_block.StructValue 获取数据库 ID?

How to obtain database id from the struct_block.StructValue in the wagtail block template?

为 wagtail StreamField 块构建自定义模板我发现自己处于需要以某种方式将当前块的 ID 传递给其他视图的情况。

例如,当 URL 在特定区块中被点击时,着陆页 view 必须准确知道 URL 在哪个区块中被点击。然后 view 可以提取与特定块相关联但不一定在视觉上呈现给用户的其他信息。

我目前的策略是使用snippets,所以我可以通过snippet的ID,view可能会获得相关但事先隐藏的数据。

这个效果还不错,但是人们不得不在两个地方编辑内容,我不得不看他们悲伤的脸。

似乎块模板上下文中的 value 变量是 wagtail.core.blocks.struct_block.StructValue 的一个实例,它使我可以访问块的所有字段,但似乎没有显示它在数据库中的足迹。

此外 value 有一个有趣的属性:value.block,它似乎是用于构建块的实际模型的实例,但我还是找不到任何有用的东西,比如 idpk 允许在数据库中识别该实例。

有办法吗?

您在 StreamField 的数据库表示中看到的块 ID 是由封闭的 StreamBlock 实现的细节,因此我们可以跟踪每个块在流中添加/移动/删除时的历史记录。流中的项目不知道它们自己的 ID - 这是因为它们可能是任何可能的数据类型(例如,CharBlock 产生一个字符串值,并且您不能将 ID 附加到字符串)。因此,块模板也无法访问 ID。

要访问 ID,您需要使用每次迭代 StreamField 值(或访问它)时返回的 BoundBlock(或更准确地说,StreamChild)对象按索引,例如模板代码中的 page.body[0]page.body.0);这个对象是块值的包装器,它知道块的类型和 ID。 (此处文档中有关 BoundBlock 的更多背景信息:http://docs.wagtail.io/en/v2.0/topics/streamfield.html#boundblocks-and-values

{% for block in page.body %}
    {% include_block block with id=block.id %}
{% endfor %}

这里blockStreamChild的一个实例,它有'value'、'block_type'和'id'属性。通常,{% include_block %} 标签只会将 value 变量传递给块模板,但在这里我们将 id 作为附加变量传递,现在可以在该块模板中使用。

StreamField 块不是 'real' 数据库对象,因此要根据您需要扫描 StreamField 的 ID 再次检索值,使用如下代码:

value = None
for block in page.body:
    if block.id == requested_id:
        value = block.value
        break

在显示您的区块的 HTML 文件中,尝试添加

{% with block.id|stringformat:"s" as block_id %}
 {{ block_id }}
{% endwith %}