I have the following StructBlock
and Page
model:
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)
I want to render the attributes of post_1
and post_2
in the 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
renders the URL fine. However, value.post_1.hero_title
is blank.
How do I render the Page attributes?
CodePudding user response:
When you use PageChooserBlock()
with no further options specified, Wagtail does not know in advance what the page type will be when retrieving it, and so it returns a basic Page
instance which only consists of the basic fields common to all page types, such as title
.
In this case, presumably only pages of PostPage should be allowed for these choosers, so you can specify that in the PageChooserBlock definition:
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
With this change, the chooser will only allow selecting pages of type PostPage, and on the template, value.post_1
and value.post_2
will be returned as full PostPage instances, allowing you to use hero_title
.
Alternatively, if you aren't able to make this change because there are multiple allowed page types, you can force it to fetch the full page object with .specific
:
{% with value.post_1.specific as post_1 %}
{{ post_1.url }}
{{ post_1.hero_title }}
{% endwith %}
However, each call to specific
will make an additional database query.