【问题标题】:Wagtail Streamblock Template RenderingWagtail Streamblock 模板渲染
【发布时间】:2021-06-08 16:09:17
【问题描述】:

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

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 这样的值,因为输出是空白的。

有什么好方法可以将可排序块添加到另一个可以拼出可排序块内容的块?

【问题讨论】:

    标签: django wagtail


    【解决方案1】:

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

    <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 直接返回子值列表 - 没有中间 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 %}

    【讨论】:

    • 这太棒了,你给了我三个很好的答案。我认为 ListBlock 是一个很好的答案,但是当我尝试切换它时,我得到了一个属性错误,现在我知道它与语法相关。感谢您提供全面的信息。
    猜你喜欢
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 2013-07-11
    • 2012-05-08
    相关资源
    最近更新 更多