在 StreamField 中显示时,如何在模型中渲染页面属性?

How to render Page attributes in a model when displayed in StreamField?

我有以下 StructBlockPage 型号:

class PostGrid(blocks.StructBlock):
    title = blocks.CharBlock()
    post_1 = blocks.PageChooserBlock()
    post_2 = blocks.PageChooserBlock()

    class Meta:
        template = 'post-grid.html'

class BlogIndex(Page):
    body = StreamField([('POSTS', PostGrid()),])

    class Meta:
        template = 'base.html'

class PostPage(Page):
    hero_title =  models.CharField(max_length=255)

我想在 body StreamField 中呈现 post_1post_2 的属性:

base.html:

{% for block in page.body %}
    {% include_block block %}
{% endfor %}

post-grid.html:

{{ value.post_1.url }}
{{ value.post_1.hero_title }}

value.post_1.url 渲染 URL 很好。但是,value.post_1.hero_title 是空白的。

如何呈现页面属性?

当您使用 PageChooserBlock() 且未指定其他选项时,Wagtail 事先不知道检索页面时的页面类型,因此它 returns 一个基本的 Page只包含所有页面类型通用的基本字段的实例,例如title.

在这种情况下,大概只允许 PostPage 页面用于这些选择器,因此您可以在 PageChooserBlock 定义中指定:

class PostGrid(blocks.StructBlock):
    title = blocks.CharBlock()
    post_1 = blocks.PageChooserBlock(page_type='myapp.PostPage')
    post_2 = blocks.PageChooserBlock(page_type='myapp.PostPage')
    # replace 'myapp' with your app name

通过此更改,选择器将只允许选择 PostPage 类型的页面,并且在模板上,value.post_1value.post_2 将作为完整的 PostPage 实例返回,允许您使用 hero_title.

或者,如果您因为有多种允许的页面类型而无法进行此更改,您可以使用 .specific:

强制它获取完整的页面对象
{% with value.post_1.specific as post_1 %}
    {{ post_1.url }}
    {{ post_1.hero_title }}
{% endwith %}

但是,每次调用 specific 都会进行一次额外的数据库查询。