Reputation: 115
I am trying to make a blog listing page using wagtail 2.13 but only managed to get {{ post.date }}
and {{ post.url }}
parts working.
{{ post.heading }}
and {{ post.standfirst }}
do not appear. I tried some permutations like {{ post.heading }}
{{ post.content.heading }}
{{ post.block.heading }}
but they did not work.
What would be the correct {{ }} query to use here?
Image of partially working listing
#models.py
from django.db import models
from wagtail.core.models import Page
from wagtail.core.fields import StreamField
from wagtail.core import blocks
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.images.blocks import ImageChooserBlock
richtext_features = [
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
"ol", "ul", "hr",
"link", "document-link",
"image", "embed",
"code", "blockquote",
"superscript", "subscript", "strikethrough",
]
class BlogListingPage(Page):
"""Listing page lists all the Blog pages."""
template = "home/home_page.html"
custom_title = models.CharField(
max_length=255,
blank=False,
null=False,
help_text='Overwrites the default title',
)
content_panels = Page.content_panels + [
FieldPanel("custom_title"),
]
def get_context(self, request, *args, **kwargs):
"""Adding custom stuff to our context."""
context = super().get_context(request, *args, **kwargs)
context["posts"] = BlogPage.objects.live().public().order_by('-date')
return context
class BlogPage(Page):
""" For individual blog pages."""
author = models.CharField(max_length=255, default="Niq")
date = models.DateField("Post date")
content = StreamField([
('heading', blocks.CharBlock(form_classname="full title")),
('standfirst', blocks.CharBlock()),
('paragraph', blocks.RichTextBlock(features=richtext_features)),
('image', ImageChooserBlock()),
], block_counts={
'heading': {'min_num': 1, 'max_num': 1,},
'standfirst': {'max_num': 1,},
})
content_panels = Page.content_panels + [
FieldPanel('author'),
FieldPanel('date'),
StreamFieldPanel('content'),
]
template = "blog/blog_page.html"
#home_page.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
{% for post in posts %}
<div class="row mt-5 mb-5">
<div class="col-sm-9">
<a href="{{ post.url }}">
test test
<h2>{{ post.heading }}</h2>
<h2>{{ post.standfirst }}</h2>
<h2>{{ post.date }}</h2>
<a href="{{ post.url }}" class="btn btn-primary mt-4">Read More</a>
</a>
</div>
</div>
{% empty %}
<h2>No posts</h2>
{% endfor %}
</div>
{% endblock content %}
Upvotes: 1
Views: 117
Reputation: 25227
Items within a StreamField behave as a list - you can't access them by name, only by their position. In general, something like post.content.heading
could not work, because a StreamField could have multiple heading items, or none at all. (In this case, your block_counts
definition prevents that, but that doesn't change the way that elements are accessed.)
As a way around this, you could define a heading
method or property on BlogPage
, which loops over the StreamField value to find a block of the appropriate type:
class BlogPage(Page):
# ...
@property
def heading(self):
for block in self.content:
if block.block_type == 'heading':
return block.value
You will then be able to access this property from the template, using {{ post.heading }}
.
Upvotes: 1