Wagtail Streamblock 模板渲染

Wagtail Streamblock Template Rendering

我正在尝试创建一个允许我添加多个块的块,其中每个块在大小估算器中的大小不同。

class SizeItem(blocks.StructBlock):
    name = blocks.CharBlock(required=True)
    image = ImageChooserBlock(required=True)
    description = blocks.TextBlock(required=True)

    class Meta: #noqa
        icon = 'arrows-up-down'
        label = 'Size Estimator Item'


class SizeEstimator(blocks.StructBlock):
    description = blocks.TextBlock(required=False)
    size_items = blocks.StreamBlock([
        ('size_item', SizeItem())
    ], required=False)

    class Meta: #noqa
        template = 'streams/size_estimator.html'
        icon =  'list-ul'
        label = 'Size Estimator'

问题是我需要将名称、图像和描述全部分组到 SizeEstimator 模板的不同区域:

<div>
    <div>
        <ul>
            <li>names</li>
        </ul>
    </div>
    <div>
        <div>
            images
        </div>
    </div>
    <div>
        descritions
    </div>
</div>

所以我无法在 SizeItem 上使用模板,因为无法在 SizeEstimator 模板中分隔各个部分。但如果我尝试:

<div class="se-wrap flexy">
  <div class="se-sizes">
    {% for item in self.size_items %}
      <div class="se-size-btn">
        {{item}}
      </div>
    {% endfor %}
  </div>
</div>

我得到了每个 SizeItem 属性名称和值的纯文本。我不能只提取像 item.name 这样的值,因为输出是空白的。

将可订购块添加到另一个块的好方法是什么,您可以在其中拼凑出可订购块的内容?

由于您已将 size_items 定义为 StreamBlock,因此循环遍历 self.size_items 将为您提供包含 block_typevalueStreamChild 个对象序列属性。在这种情况下,block_type 将始终是 'size_item'(因为这是该流中定义的唯一块类型),而 value 将是一个 SizeItem 的数据,作为字典。因此,您可以使用如下模板访问该项目的各个字段:

<div class="se-wrap flexy">
  <div class="se-sizes">
    {% for item in self.size_items %}
      <div class="se-size-btn">
        {{item.value.name}}
      </div>
    {% endfor %}
  </div>
  <div class="se-images">
    {% for item in self.size_items %}
      <div class="se-size-btn">
        {% image item.value.image width-400 %}
      </div>
    {% endfor %}
  </div>
</div>

如果您将 size_items 定义为 size_items = blocks.ListBlock(SizeItem(), required=False),这将简化事情,因为 ListBlock returns 直接是子值列表 - 没有中间值 StreamChild 对象来识别每个块的类型,因此您可以在模板中编写 {{item.name}}

您可能会发现将 get_context 方法添加到 SizeEstimator 块以设置一些要传递给模板的变量,而不是在模板中解压缩数据:

class SizeEstimator(blocks.StructBlock):
    # ...
    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)

        names = []
        images = []
        descriptions = []

        for item in value:
            names.append(item.value['name'])  # or item['name'] if you're using a ListBlock
            images.append(item.value['image'])
            descriptions.append(item.value['description'])

        # make these lists available to the template
        context['names'] = name
        context['images'] = images
        context['descriptions'] = descriptions

        return context

然后您就可以在模板中写入 {% for name in names %}