Page not found when following wagtail tutorial adding tags

26 views Asked by At

I wanted to add tags to posts in the quickstart Wagtail blog by following the (Wagtail tutorial). When I clicked the "foood" tag that I added to one of my posts, I ran into a Page not found (404) error. Check out the screenshot below Page not found debug output

Here is my class BlogTagIndexPage(Page) in blog/models.py

# Add BlogTagIndexPage
class BlogTagIndexPage(Page):

    def get_context(self, request):

        # Filter by tag
        tag = request.GET.get('tag')
        blogpages = BlogPage.objects.filter(tags__name=tag)

        # Update template context
        context = super().get_context(request)
        context['blogpages'] = blogpages
        return context

and my blog_tag_index_page.html in blog/templates/blog/

{% extends "base.html" %}
{% load wagtailcore_tags %}

{% block content %}

    {% if request.GET.tag %}
        <h4>Showing pages tagged "{{ request.GET.tag }}"</h4>
    {% endif %}
        
    {% for blogpage in blogpages %}

          <p>
              <strong><a href="{% pageurl blogpage %}">{{ blogpage.title }}</a></strong><br />
              <small>Revised: {{ blogpage.latest_revision_created_at }}</small><br />
          </p> 

    {% empty %}
        No pages found with that tag.
    {% endfor %}

{% endblock %}

What am I missing?

This is my models.py. Class BlogPage is included:

from django.db import models
from django import forms

from modelcluster.fields import ParentalKey, ParentalManyToManyField
# add tags to allow users to view tagged content
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.models import TaggedItemBase


# add wagtail classes and methods
from wagtail.models import Page, Orderable
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel, InlinePanel, MultiFieldPanel
from wagtail.search import index

# add snippets
from wagtail.snippets.models import register_snippet

# Add BlogTagIndexPage
class BlogTagIndexPage(Page):

    def get_context(self, request):

        # Filter by tag
        tag = request.GET.get('tag')
        blogpages = BlogPage.objects.filter(tags__name=tag)

        # Update template context
        context = super().get_context(request)
        context['blogpages'] = blogpages
        return context

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

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

    # add the get_context method:
    def get_context(self, request):
        # Update context to include only published posts, ordered by reverse-chron
        context = super().get_context(request)
        blogpages = self.get_children().live().order_by('-first_published_at')
        context['blogpages'] = blogpages
        return context


class BlogPageTag(TaggedItemBase):
    content_object = ParentalKey(
        'BlogPage',
        related_name='tagged_items',
        on_delete=models.CASCADE
    )

class BlogPage(Page):
    date = models.DateField("Post date")
    intro = models.CharField(max_length=250)
    body = RichTextField(blank=True)

    # the main_image method:
    def main_image(self):
        gallery_item = self.gallery_images.first()
        if gallery_item:
            return gallery_item.image
        else:
            return None

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

    # Add authors:
    authors = ParentalManyToManyField('blog.Author', blank=True)

    # Add tags:
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True)

    content_panels = Page.content_panels + [

        # Add MultiFieldPanel including date panel, authors panel
            MultiFieldPanel([
            FieldPanel('date'),
            FieldPanel('authors', widget=forms.CheckboxSelectMultiple),
             # Add field for tags:
            FieldPanel('tags'),
        ], heading="Blog information"),

        FieldPanel('intro'),
        FieldPanel('body'),
        InlinePanel('gallery_images', label="Gallery images"),
    ]

class BlogPageGalleryImage(Orderable):
    page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')
    image = models.ForeignKey(
        'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
    )
    caption = models.CharField(blank=True, max_length=250)

    panels = [
        FieldPanel('image'),
        FieldPanel('caption'),
    ]

@register_snippet
class Author(models.Model):
    name = models.CharField(max_length=255)
    author_image = models.ForeignKey(
        'wagtailimages.Image', null=True, blank=True,
        on_delete=models.SET_NULL, related_name='+'
    )

    panels = [
        FieldPanel('name'),
        FieldPanel('author_image'),
    ]

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = 'Authors'

This is my blog_page.html template:

{% extends "base.html" %}

{% load wagtailcore_tags wagtailimages_tags %}

{% block body_class %}template-blogpage{% endblock %}

{% block content %}
    <h1>{{ page.title }}</h1>
    <p class="meta">{{ page.date }}</p>

        <!-- Add authors multi-field panel to blog page template: -->
    {% with authors=page.authors.all %}
        {% if authors %}
            <h3>Posted by:</h3>
            <ul>
                {% for author in authors %}
                    <li style="display: inline">
                        {% image author.author_image fill-40x60 style="vertical-align: middle" %}
                        {{ author.name }}
                    </li>
                {% endfor %}
            </ul>
        {% endif %}
    {% endwith %}


    <div class="intro">{{ page.intro }}</div>

    {{ page.body|richtext }}

        <!-- image gallery -->
    {% for item in page.gallery_images.all %}
        <div style="float: inline-start; margin: 10px">
            {% image item.image fill-320x240 %}
            <p>{{ item.caption }}</p>
        </div>
    {% endfor %}

    <p><a href="{{ page.get_parent.url }}">Return to blog</a></p>

    <!-- Add this: -->
    {% with tags=page.tags.all %}
        {% if tags %}
            <div class="tags">
                <h3>Tags</h3>
                {% for tag in tags %}
                    <a href="{% slugurl 'tags' %}?tag={{ tag }}"><button type="button">{{ tag }}</button></a>
                {% endfor %}
            </div>
        {% endif %}
    {% endwith %}

{% endblock %}
1

There are 1 answers

0
siralbert On

Just forgot to create a BlogTagIndexPage and give it the slug "tags" on the Promote tab. Exact instructions from wagtail tutorial are shown below. I bolded the relevant parts of the instructions. Thanks to Gasman for pointing that out.

After migrating the new changes, create a new BlogTagIndexPage in the admin interface. To create the BlogTagIndexPage, follow the same process you followed in creating the BlogIndexPage and give it the slug “tags” on the Promote tab. This means the BlogTagIndexPage is a child of the home page and parallel to Our Blog in the admin interface.