Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying blog posts on homepage in Wagtail

I am building a Wagtail site that has blog postings listed on a blog index page, but I would also like to display the latest three posts on the home page of the website as well. My current code to display blogs on the blog index page is as follows:

blog_index_page.html:

{% for blog in blogs %}
  <div class="col-sm-12">
    <div class="blog-post post-format-image">
      <div class="blog-post-side">
        <div class="blog-post-date">
          <p class="date-day">{{ blog.date.day }}</p>
          <p class="date-month">{{ blog.date|date:"M" }}</p>
        </div>
      </div>

      <div class="blog-post-content">
        <div class="post-media">
          {% image blog.main_image width-1225 %}
        </div>
      <div class="post-info">
        <h3 class="post-title"><a href="{{ blog.slug }}">{{ blog.title }}</a></h3>
      </div>
      <div class="post-content">
        <p>{{ blog.intro }}</p>
      </div>
      <a class="btn btn-primary btn-sm" href="{{ blog.slug }}">Read More<i class="fa iconright fa-arrow-circle-right"></i></a>
    </div>
  </div>
{% endfor %}

Blog models.py

class ResourcePage(Page):
    main_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    date = models.DateField(blank=True, null=True)
    intro = models.CharField(max_length=250)
    body = RichTextField(blank=True)

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
        index.SearchField('body'),
    ]

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        ImageChooserPanel('main_image'),
        FieldPanel('intro'),
        FieldPanel('body', classname='full'),
    ]

class ResourceIndexPage(Page):
    intro = RichTextField(blank=True)

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
    ]

    @property
    def blogs(self):
        # Get list of live blog pages that are descendants of this page
        blogs = ResourcePage.objects.live().descendant_of(self)

        # Order by most recent date first
        blogs = blogs.order_by('date')

        return blogs

    def get_context(self, request):
        # Get blogs
        blogs = self.blogs

        # Filter by tag
        tag = request.GET.get('tag')
        if tag:
            blogs = blogs.filter(tags__name=tag)

        # Pagination
        page = request.GET.get('page')
        paginator = Paginator(blogs, 5)  # Show 5 blogs per page
        try:
            blogs = paginator.page(page)
        except PageNotAnInteger:
            blogs = paginator.page(1)
        except EmptyPage:
            blogs = paginator.page(paginator.num_pages)

        # Update template context
        context = super(ResourceIndexPage, self).get_context(request)
        context['blogs'] = blogs
        return context

    def get_sitemap_urls(self):
        return [
            {
                'location': self.full_url,
                'lastmod': self.latest_revision_created_at,
                'changefreq': 'monthly',
                'priority': .5
            }
        ]

    ResourceIndexPage.content_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('intro', classname="full"),
        InlinePanel('related_links', label="Related links"),
    ]

    ResourceIndexPage.promote_panels = Page.promote_panels

I want to also display the latest three posts on the home page, but I'm not sure how to pass them from the blog section of the site to the home page. I am attempting to do something like this:

{% for blog in blogs %}
  <div class="carousel-item">
    <a href="/education/{{ blog.slug }}">{% image blog.main_image width-360 %}</a>
    <div class="panel panel-default">
      <div class="panel-body">
        <h5><a href="blog-single-post.html">{{ blog.title }}</a></h5>
        <p>{{ blog.intro }}</p>
      </div>
    </div>
 </div>
{% endfor %}

Home page models.py

from __future__ import absolute_import, unicode_literals

from django.db import models
from django.http import HttpResponseRedirect

from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.fields import RichTextField, StreamField
from wagtail.wagtailcore import blocks
from wagtail.wagtailcore.blocks import URLBlock, DateBlock
from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel
from wagtail.wagtailadmin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.wagtailimages.blocks import ImageChooserBlock

from resources.models import ResourcePage


class HomePage(Page):

    def blogs(ResourcePage):
        # Get list of live blog pages that are descendants of the ResourceIndexPage page
        blogs = ResourcePage.objects.all()

        # Order by most recent date first
        blogs = resources.order_by('date')

        return blogs

Nothing is showing up on the page. What am I doing wrong?

like image 527
kbdev Avatar asked Jan 05 '23 03:01

kbdev


1 Answers

As standard, the page object is available within the template under the variable name page. (You may also have seen self being used, but page is preferred as it's compatible with other template engines such as Jinja2.) This means that if you define a blogs method on the page model, you can access it as page.blogs:

{% for blog in page.blogs %}

If you want to refer to it as just blogs, you'll need to define a get_context method that explicitly adds that to the template context:

class HomePage(Page):
    ...
    def get_context(self, request):
        context = super(HomePage, self).get_context(request)
        context['blogs'] = self.blogs()
        return context

Also, the line def blogs(ResourcePage): is incorrect - you're confusing it with a class definition. This should be: def blogs(self):

like image 178
gasman Avatar answered Jan 11 '23 08:01

gasman