Как получить идентификатор базы данных из struct_block.StructValue в шаблоне блока трясогузки?
Создание собственного шаблона для трясогузки StreamField
Блок Я попал в ситуацию, в которой мне нужно как-то передать идентификатор текущего блока другим представлениям.
Например, когда URL-адрес нажимается в конкретном блоке, целевая страница view
должен точно знать, в каком из блоков был нажат URL. Тогда view
может извлекать другую информацию, которая связана с конкретным блоком, но не обязательно визуально представлена пользователю.
Моя текущая стратегия использует snippets
так что я могу передать идентификатор snippet
и view
может получить связанные, но заранее скрытые данные.
Это работает не так уж плохо, но люди должны редактировать контент в двух местах, и я должен смотреть на их грустные лица.
Кажется, что value
переменная в контексте шаблона блока является экземпляром wagtail.core.blocks.struct_block.StructValue
, который дает мне доступ ко всем полям блока, но, похоже, не показывает его след в БД.
В дальнейшем value
имеет интересный атрибут: value.block
Кажется, это экземпляр реальной модели, использованной для построения блока, но опять же я не могу найти ничего полезного, например, id
или же pk
что позволило бы идентифицировать этот экземпляр в базе данных.
Есть ли способ?
1 ответ
Идентификаторы блоков, которые вы видите в представлении базы данных StreamField, являются подробностями, реализованными включающим StreamBlock, так что мы можем отслеживать историю каждого блока, когда он добавляется / перемещается / удаляется из потока. Элементы в потоке не знают своего собственного идентификатора - это потому, что они могут быть любого возможного типа данных (например, CharBlock
создает строковое значение, и вы не можете прикрепить идентификатор к строке). В результате шаблон блока также не имеет доступа к идентификатору.
Чтобы получить доступ к идентификатору, вам необходимо использовать BoundBlock
(или, точнее, StreamChild
) объект, который возвращается всякий раз, когда вы перебираете значение StreamField (или обращаетесь к нему по индексу, например, page.body[0]
или же page.body.0
в коде шаблона); этот объект является оберткой вокруг значения блока, который знает тип и идентификатор блока. (Больше информации на BoundBlock
в документации здесь: http://docs.wagtail.io/en/v2.0/topics/streamfield.html)
{% for block in page.body %}
{% include_block block with id=block.id %}
{% endfor %}
Вот block
это пример StreamChild
, который имеет свойства 'value', 'block_type' и 'id'. Обычно {% include_block %}
тег будет просто передавать на value
переменная в шаблоне блока, но здесь мы проходим id
в качестве дополнительной переменной, которая теперь будет доступна в этом блочном шаблоне.
Блоки StreamField не являются "реальными" объектами базы данных, поэтому для получения значения снова на основе идентификатора вам нужно будет сканировать через StreamField, используя такой код, как:
value = None
for block in page.body:
if block.id == requested_id:
value = block.value
break
В HTML-файле, который отображает ваш блок, попробуйте добавить
{% with block.id|stringformat:"s" as block_id %}
{{ block_id }}
{% endwith %}