user6806370
user6806370

Reputation:

Wagtail: Template tag with call to routablepageurl throwing AttributeError

I'm trying to build a simple blog in Wagtail, and trying to figure out how everything in it fits together and why things don't work is driving me up the wall. I keep getting AttributeError: 'str' object has no attribute 'relative_url' when I try to load an 'About' page, and I think it has to do with a navbar.html I'm bringing into base.html with an inclusion tag. I can't make sense of the error, can anyone help break it down?

Navbar.html

{% load static wagtailcore_tags blogapp_tags wagtailroutablepage_tags %}

<div class="container" id="nav-container">
  <nav class="navbar navbar-expand-sm py-0 px-0" id="main-nav">
  <button class="navbar-toggler" data-toggle="collapse" data-target="#navbarCollapse">
    <span class="navbar-toggler-icon"></span>
  </button>
  <form role="search" method="get" class="form-inline pt-3 form-search" action="{% routablepageurl home_page 'post_search' %}">
    <input type="text" name="q" id="search-bar" class="form-control mr-sm-2 search-query" type="search" placeholder="Search&hellip;" title="Search for:" aria-label="Search">
    <button class="btn btn-outline-danger my-2 my-sm-0" name="submit" id="search-button" type="submit" value="Search">Search</button>
  </form>
  <div class="collapse navbar-collapse" id="navbarCollapse">
    <ul class="navbar-nav mt-2 ml-auto">
      <li class="nav-item">
        <a href="/about" class="nav-link">About</a>
      </li>
      <li class="nav-item">
        <a href="#" class="nav-link">Archive</a>
      </li>
    </ul>
  </div>
  </nav> 
</div>

Models.py

class HomePage(RoutablePageMixin, Page):
    description = models.CharField(max_length=255, blank=True, null=True)

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

    def get_context(self, request, *args, **kwargs):
        context = super(HomePage, self).get_context(request, *args, **kwargs)
        context['posts'] = self.posts
        context['home_page'] = self
        context['search_type'] = getattr(self, 'search_type', '')
        context['search_term'] = getattr(self, 'search_term', '')
        return context


    def get_posts(self):
        return BlogPage.objects.descendant_of(self).live()

...

    @route(r'^search/$')
    def post_search(self, request, *args, **kwargs):
        search_query = request.GET.get('q', None)
        self.posts = self.get_posts()
        if search_query:
            self.posts = self.posts.filter(body__icontains=search_query)
            self.search_term = search_query
            self.search_type = 'search'
        return Page.serve(self, request, *args, **kwargs)


class AboutPage(Page):
    body = RichTextField(blank=True)

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

about_page.html

{% extends "home/base.html" %}
{% load static wagtailcore_tags blogapp_tags wagtailroutablepage_tags %}

{% block content %}

<div class="container mt-4" id="nav-container">
  <h3 class="blog-text">About</h3>
  <br>
  <div class="row">
    <div class="col-md-8">
      <p class="pt-0 mb-5">{{ page.body }}</p>
    </div>
  </div>
</div>

{% endblock %}

Full project here:

https://bitbucket.org/nicecore/adiscaday-wagtail/src/master/

Full traceback here:

http://dpaste.com/1T65ZCV

Upvotes: 1

Views: 1484

Answers (2)

gasman
gasman

Reputation: 25227

The root page of a site is always available as the variable request.site.root_page, so rather than relying on home_page to be defined on every page type you create, you could change the tag to:

{% routablepageurl request.site.root_page.specific 'post_search' %}

Upvotes: 2

user6806370
user6806370

Reputation:

@gasman in the comments of my original post helpfully suggested that the home_page variable was somehow being overwritten, so I copied the get_context method from my BlogPage model in AboutPage (starting to wonder whether I shouldn't just use an instance of BlogPage for my About page and just leave the unneeded fields blank...) and it seems to be working:

class AboutPage(Page):
    body = RichTextField(blank=True)

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

    def get_context(self, request, *args, **kwargs):
        context = super(AboutPage, self).get_context(request, *args, **kwargs)
        context['home_page'] = self.get_parent().specific
        context['about'] = self
        return context

Any insight into why home_page was being overwritten so I can avoid this issue in the future would be greatly appreciated!

Upvotes: 0

Related Questions