Как отобразить атрибуты страницы в модели при отображении в StreamField?
У меня есть следующая StructBlock и Page модель:
class PostGrid(blocks.StructBlock):
title = blocks.CharBlock()
post_1 = blocks.PageChooserBlock()
post_2 = blocks.PageChooserBlock()
class Meta:
template = 'post-grid.html'
class BlogIndex(Page):
body = StreamField([('POSTS', PostGrid()),])
class Meta:
template = 'base.html'
class PostPage(Page):
hero_title = models.CharField(max_length=255)
Я хочу отобразить атрибуты post_1 и post_2 в body StreamField:
base.html:
{% for block in page.body %}
{% include_block block %}
{% endfor %}
post-grid.html:
{{ value.post_1.url }}
{{ value.post_1.hero_title }}
value.post_1.url отображает URL нормально. Однако value.post_1.hero_title остается пустым.
Как отобразить атрибуты страницы?
Когда вы используете PageChooserBlock() без указания дополнительных опций, Wagtail не знает заранее, каким будет тип страницы при ее получении, и поэтому возвращает базовый экземпляр Page, который состоит только из основных полей, общих для всех типов страниц, таких как title.
В этом случае, предположительно, только страницы PostPage должны быть разрешены для этих переключателей, поэтому вы можете указать это в определении PageChooserBlock:
class PostGrid(blocks.StructBlock):
title = blocks.CharBlock()
post_1 = blocks.PageChooserBlock(page_type='myapp.PostPage')
post_2 = blocks.PageChooserBlock(page_type='myapp.PostPage')
# replace 'myapp' with your app name
При таком изменении выборщик позволит выбирать только страницы типа PostPage, а в шаблоне value.post_1 и value.post_2 будут возвращаться как полные экземпляры PostPage, что позволит вам использовать hero_title.
Альтернативно, если вы не можете сделать это изменение, потому что есть несколько разрешенных типов страниц, вы можете заставить его получить полный объект страницы с помощью .specific:
{% with value.post_1.specific as post_1 %}
{{ post_1.url }}
{{ post_1.hero_title }}
{% endwith %}
Однако, каждый вызов specific будет выполнять дополнительный запрос к базе данных.