无法在模板Wagtail中的StreamBlock内呈现Listblock

2024-10-02 06:28:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Listblock中有StructBlock,所有这些都位于类BannerBlock中,如下所示:

class BannerBlock(blocks.StreamBlock):
    """
    Blocks for displaying individual banners
    """
    
    banners = blocks.ListBlock(
        blocks.StructBlock(
            [
                ('image', ImageChooserBlock(required=True)),
                ('title', blocks.CharBlock(required=True, max_length=128)),
                ('description', blocks.CharBlock(required=True, max_length=1024)),
                ('link', blocks.URLBlock(required=False)),
            ]
        )
    )
    
    class Meta:
        template = "home/banner_block.html"
        icon = "placeholder"
        label = "Banners"

模板块如下所示:

{% load wagtailimages_tags %}

<!-- Banner -->
<div id="banner">
    {% for banner in self.banners %}
        <article data-position="bottom right">
            <div class="inner">
                {% image banner.image original as image %}
                <img src="{{ image.url }}" alt="">
                <div class="features">
                    <a href="{{ banner.link.url }}" class="c-accent alt no-bg">
                    <h2>{{ banner.title }}</h2>
                    <p>{{ banner.description }}</p>
                    </a>
                </div>
            </div>
        </article>
    {% endfor %}
</div>

最后,我尝试按如下方式渲染每个横幅(Listblock):

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

但是,每个Listblock都作为列表项呈现为纯文本。 如何正确渲染每个项目? 多谢各位


Tags: imagedivtruefortitlerequiredblockclass
1条回答
网友
1楼 · 发布于 2024-10-02 06:28:14

我假设页面模型上的banners_collection字段定义为:

banners_collection = StreamField(BannerBlock())

指定要在StreamField的顶层使用的StreamBlock,而不是更基本的设置

some_stream = StreamField([
    ('first_block_type', some_block_definition),
    ('another_block_type', some_block_definition),
])

在这里,您将传递StreamField的块列表,以便从中生成流。这意味着当您访问page.banners_collection时,它将为您提供BannerBlock值的单个实例。当您使用for block in page.banners_collection循环这个值时,实际上是在返回流中的ListBlock值,并使用include_block单独呈现它们-绕过为BannerBlock设置的模板。您的ListBlock值没有自己的模板,因此它们最终使用默认呈现

如果您对整个BannerBlock值调用include_block

{% include_block page.banners_collection %}

然后它将使用您的模板。然而,还有一个次要的问题——在生产线上

{% for banner in self.banners %}

self.banners无效,因为流值的行为是序列,而不是字典。您不能按名称查找banners子项-您需要在子项列表上循环查找类型为banners的子项。(在您的情况下,您可以跳过该检查,因为banners是流中唯一可用的块类型)。正确的模板代码如下所示:

<div id="banner">
    {% for block in self %}
        {# the 'block' object here has properties block_type (which is always 'banners' here) and value #}
        {% for banner in block.value %}
            {# banner is a StructBlock value, with image, title, description, link properties #}
            <article data-position="bottom right">
                <div class="inner">
                    {% image banner.image original as image %}
                    ...
               </div>
           </article>
        {% endfor %}
    {% endfor %}
</div>

但是,您确定除了StreamBlock之外还需要ListBlock吗?StreamBlock已经是一个块序列,因此StreamBlock中的ListBlock为您提供了一个横幅列表。如果将BannerBlock值简化为

class BannerBlock(blocks.StreamBlock):
    """
    Blocks for displaying individual banners
    """
    
    banner = blocks.StructBlock(
        [
            ('image', ImageChooserBlock(required=True)),
            ('title', blocks.CharBlock(required=True, max_length=128)),
            ('description', blocks.CharBlock(required=True, max_length=1024)),
            ('link', blocks.URLBlock(required=False)),
        ]
    )
    
    class Meta:
        template = "home/banner_block.html"
        icon = "placeholder"
        label = "Banners"

然后BannerBlock作为一个整体将是一个横幅列表,模板将成为

<div id="banner">
    {% for block in self %}
        {# block.value is now a StructBlock value #}
        <article data-position="bottom right">
            <div class="inner">
                {% image block.value.image original as image %}
                ...
           </div>
       </article>
    {% endfor %}
</div>

相关问题 更多 >

    热门问题