Leo
Leo

Reputation: 169

Unable to link blog post to its content page in Wagtail

I'm having a problem creating a link of a Blog Post to its own content page in wagtail. In my models I have two page classes, BlogPage and IndexPage. My BlogPage class is used to create the blog post, and IndexPage class is used to display a list of blog posts.

Please see models below:

from django.db import models

from modelcluster.fields import ParentalKey

from wagtail.wagtailcore.models import Page, Orderable
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtailsearch import index


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

    def child_pages(self):
        return BlogPage.objects.live()


    content_panels = Page.content_panels + [
        FieldPanel('intro', classname='full'),
    ]

    subpage_types = ['blog.BlogPage']


class BlogPage(Page):
    date = models.DateField("Post date")
    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'),
    FieldPanel('intro'),
    FieldPanel('body', classname="full")
    ]

My challenge is that I can't figure out how to link the blog post on the Index Page to its own page. Do I need to create a separate page model and html template to achieve this? or what could be the best approach to solve this problem?

Upvotes: 0

Views: 307

Answers (1)

doru
doru

Reputation: 9110

You can create an include template (it doesn't need a model) - let's name it truncated_blog_post.html - which you can then invoke in your index_page.html template. This would be the recommended approach because using a include template for a post gives the possibility to use it anywhere you need to display a list of (truncated usually) posts: when you want the posts under a certain tag, for example.

truncated_blog_post.html

{% load wagtailcore_tags %}

<article>
  <a href="{% pageurl blog %}"><h2>{{ blog.title }}</h2></a>
  <p>{{ blog.date }}</p>
  <p>{{ blog.body|truncatewords:40 }}</p>
</article>

Using the pageurl tag from wagtailcore_tags you get the relative URL of that blog post. Obviously, if you don't want to create a include template for a truncated post, you can put the article code from blog_post.html directly in the for loop in the index_page.html template.

And your index_page.html template:

....
{% for blog in blogs %}
  {% include "path/to/includes/truncated_blog_post.html" %}
{% empty %}
  No posts found
{% endfor %}
....

For this to work you have to modify the IndexPage model:

class IndexPage(Page):
    intro = RichTextField(blank=True)
    @property
    def blogs(self):
        blogs = BlogPage.objects.live()
        return blogs
    def get_context(self, request):
        # Get blogs
        blogs = self.blogs

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

    content_panels = Page.content_panels + [
    FieldPanel('intro', classname='full'),
    ]
    subpage_types = ['blog.BlogPage']

Upvotes: 2

Related Questions