Spec-Zone.ru › Wagtail 2

О блоках StreamField BoundBlocks и значениях

Все типы блоков StreamField принимают параметр template для определения того, как они будут отображаться на странице. Однако для блоков, обрабатывающих базовые типы данных Python, такие как CharBlock и IntegerBlock, существуют ограничения на область действия шаблона, поскольку встроенные типы (str, int и так далее) не могут быть «обучены» обработке шаблонов. В качестве примера рассмотрим следующее определение блока:

class HeadingBlock(blocks.CharBlock):
    class Meta:
        template = 'blocks/heading.html'

где blocks/heading.html состоит из:

<h1>{{ value }}</h1>

Это дает нам блок, который ведет себя как обычное текстовое поле, но обертывает свой вывод тегами <h1> всякий раз, когда он отображается:

class BlogPage(Page):
    body = StreamField([
        # ...
        ('heading', HeadingBlock()),
        # ...
    ])
{% load wagtailcore_tags %}

{% for block in page.body %}
    {% if block.block_type == 'heading' %}
        {% include_block block %}  {# This block will output its own <h1>...</h1> tags. #}
    {% endif %}
{% endfor %}

Такая организация — значение, которое, предположительно, представляет собой обычную строку текста, но имеет собственное пользовательское представление HTML при выводе на шаблон — обычно является очень запутанной задачей в Python, но здесь она работает, потому что элементы, получаемые при итерации по StreamField, на самом деле не являются «родными» значениями блоков. Вместо этого каждый элемент возвращается как экземпляр BoundBlock — объекта, представляющего пару значения и определения блока. Отслеживая определение блока, BoundBlock всегда знает, какой шаблон отобразить. Чтобы получить базовое значение — в данном случае текстовое содержимое заголовка — необходимо получить доступ к block.value. Действительно, если вы выведете {% include_block block.value %} на странице, вы увидите, что оно отображается как обычный текст без тегов <h1>.

(Более точно, элементы, возвращаемые при итерации по StreamField, являются экземплярами класса StreamChild, который предоставляет свойство block_type и также value.)

Опытные разработчики Django могут найти полезным сравнение этого с классом BoundField в рамках фреймворка форм Django, который представляет собой пару значения поля формы и соответствующего определения поля формы и, следовательно, знает, как отобразить значение как поле HTML-формы.

Большую часть времени вам не нужно беспокоиться об этих внутренних деталях; Wagtail будет использовать отображение шаблона там, где вы ожидаете его увидеть. Однако есть определенные случаи, когда иллюзия неполна — в частности, при обращении к дочерним элементам ListBlock или StructBlock. В этих случаях нет обертки BoundBlock, и поэтому нельзя полагаться на то, что элемент знает собственное отображение шаблона. Например, рассмотрим следующую настройку, где наш HeadingBlock является дочерним элементом блока StructBlock:

class EventBlock(blocks.StructBlock):
    heading = HeadingBlock()
    description = blocks.TextBlock()
    # ...

    class Meta:
        template = 'blocks/event.html'

В blocks/event.html:

{% load wagtailcore_tags %}

<div class="event {% if value.heading == 'Party!' %}lots-of-balloons{% endif %}">
    {% include_block value.heading %}
    - {% include_block value.description %}
</div>

В этом случае value.heading возвращает простое строковое значение, а не BoundBlock; это необходимо, поскольку в противном случае сравнение в {% if value.heading == 'Party!' %} никогда не будет успешным. Это, в свою очередь, означает, что {% include_block value.heading %} отображается как простая строка без тегов <h1>. Чтобы получить HTML-отображение, необходимо явно обратиться к экземпляру BoundBlock через value.bound_blocks.heading:

{% load wagtailcore_tags %}

<div class="event {% if value.heading == 'Party!' %}lots-of-balloons{% endif %}">
    {% include_block value.bound_blocks.heading %}
    - {% include_block value.description %}
</div>

На практике было бы более естественно и наглядно сделать тег <h1> явным в шаблоне EventBlock:

{% load wagtailcore_tags %}

<div class="event {% if value.heading == 'Party!' %}lots-of-balloons{% endif %}">
    <h1>{{ value.heading }}</h1>
    - {% include_block value.description %}
</div>

Это ограничение не относится к значениям StructBlock и StreamBlock в качестве дочерних элементов StructBlock, поскольку Wagtail реализует их как сложные объекты, которые знают собственное отображение шаблона, даже если они не обернуты в BoundBlock. Например, если StructBlock вложен в другой StructBlock, как в:

class EventBlock(blocks.StructBlock):
    heading = HeadingBlock()
    description = blocks.TextBlock()
    guest_speaker = blocks.StructBlock([
        ('first_name', blocks.CharBlock()),
        ('surname', blocks.CharBlock()),
        ('photo', ImageChooserBlock()),
    ], template='blocks/speaker.html')

тогда {% include_block value.guest_speaker %} в шаблоне EventBlock получит отображение шаблона из blocks/speaker.html как и предполагалось.

Вкратце, взаимодействия между BoundBlocks и обычными значениями работают по следующим правилам:

  1. При итерации по значению StreamField или StreamBlock (как в {% for block in page.body %}) вы получите последовательность BoundBlocks.
  2. Если у вас есть экземпляр BoundBlock, вы можете получить доступ к обычному значению как block.value.
  3. Обращение к дочернему элементу StructBlock (как в value.heading) вернет простое значение; чтобы получить BoundBlock вместо этого, используйте value.bound_blocks.heading.
  4. Аналогично, обращение к дочерним элементам ListBlock (например, for item in value) вернет простые значения; чтобы получить BoundBlocks вместо этого, используйте value.bound_blocks.
  5. Значения StructBlock и StreamBlock всегда знают, как отобразить собственные шаблоны, даже если у вас есть только простое значение, а не BoundBlock.

Изменено в версии 2.16: Значение ListBlock теперь предоставляет свойство bound_blocks; ранее это был обычный Python-список дочерних значений.

  • Предыдущая Учет доступности
  • Следующая Многосайтовая, многоэкземплярная и многоарендная системы

© 2014-present Torchbox Ltd and individual contributors.
All rights are reserved.
Licensed under the BSD License.
https://docs.wagtail.org/en/v2.16.3/advanced_topics/boundblocks_and_values.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API