3

I have 3 mains sections in my site, homepage, blog index, and blog specific. I am using the streamfield function in wagtail to order various sections in the homepage. One of those sections is for the latest three blog posts.

I have done this for the blog index page, but can't grab the latest blog posts in the streamfield.

My model looks like this

class CaseStudiesIndex(Page):
    def casestudies(pages):
       casestudies = CaseStudyPage.objects.all().order_by('-first_published_at')
       return casestudies
    intro = RichTextField(blank=True)
    content_panels = Page.content_panels + [
        FieldPanel('intro', classname="full")
    ]

class LatestPosts(blocks.StructBlock):
    static = blocks.StaticBlock(admin_text='Latest posts: no configuration needed.',)
    def casestudies(pages):
        casestudies = CaseStudyPage.objects.all().order_by('-first_published_at')[:3] 
        return casestudies

    class Meta:
        icon = 'doc-full'
        label = 'Latest Posts'
        template = 'blocks/_latestPosts.html'

class HomePage(Page):
    blocksbody = StreamField([
        ('lead_banner', LeadBanner()),
        ('latest_posts', LatestPosts()),
        ('team', Team())
    ],null=True,blank=True)


    content_panels = Page.content_panels + [
        StreamFieldPanel('blocksbody'), 
    ]

In my block folder I am calling the file fine and it renders the wrapper fine but I can't grab any of the data, I have tried a bunch of ways but nothing returns.

{% load wagtailcore_tags wagtailimages_tags %}
{% load static %}

<section>
    <div class="wrapper__inner">
        <ul>
            {% for case in self.casestudies %}
                {{case.title}}
            {% endfor %}

            {% for case in self.case_studies %}
                {{case.title}}
            {% endfor %}

            {% for case in self.latest_posts %}
                {{case.title}}
            {% endfor %}

            {% for case in page.casestudies %}
                {{case.title}}
            {% endfor %}

            {% for case in page.case_studies %}
                {{case.title}}
            {% endfor %}

            {% for case in page.latest_posts %}
                {{case.title}}
            {% endfor %}
        </ul>
    </div>
</section>

For the Blog Index page that does work I do the following.

{% extends "inner_base.html" %}
{% load wagtailcore_tags %}
{% block body_class %}template-case-studies{% endblock %}
{% block content %}
    <section>
        <div class="wrapper__inner">
            <h1>{{self.title}}</h1>
            <ul>
                {% include "blocks/CaseStudiesLatestBlock.html" %}
            </ul>
        </div>
    </section>
{% endblock %}

And the CaseStudiesLatestBlock.html which works fine looks like

{% load wagtailcore_tags wagtailimages_tags %}
{% load static %}
{% for case in self.casestudies %}
    <li>
        <strong>{{ case.title }}</strong>
    </li>
{% endfor %}

1 Answers1

2

Defining your own methods on a StructBlock won't work - the self (or value) variable you receive on the template is just a plain dict, not the StructBlock object itself. (This might seem counter-intuitive, but it's consistent with how blocks work in general: just as a CharBlock gives you a string value to work with and not a CharBlock instance, StructBlock gives you a dict rather than a StructBlock instance.)

Instead, you can define a get_context method (as documented here) to provide additional variables to the template:

class LatestPosts(blocks.StructBlock):
    static = blocks.StaticBlock(admin_text='Latest posts: no configuration needed.',)

    def get_context(self, value, parent_context=None):
        context = super(LatestPosts, self).get_context(value, parent_context=parent_context)
        context['casestudies'] = CaseStudyPage.objects.all().order_by('-first_published_at')[:3] 
        return context

You can then access the casestudies variable in the template, e.g. {% for case in casestudies %}.

gasman
  • 23,691
  • 1
  • 38
  • 56