question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Documentation examples for overriding Page.serve should not bypass get_context

See original GitHub issue

I had a couple of Pages that overrode the serve() method and noticed that the userbar wouldn’t display on these pages.

Digging through the source I figured out you have to add wagtailcore.models.PAGE_TEMPLATE_VAR to your context with a reference to the page instance.

For example:

from django.shortcuts import render
from wagtail.wagtailcore.models import Page, PAGE_TEMPLATE_VAR

class CustomPage(Page):
    def serve(self, request, *args, **kwargs):
        return render(request, self.template, {
            PAGE_TEMPLATE_VAR: self,
            'self': self
        })

I’m not sure if this is a documentation issue or a consistency issue with which context variable will be used as a reference to the Page instance. In the tutorial and docs it shows using ‘self’ but it looks like PAGE_TEMPLATE_VAR is using ‘page’.

Thanks!

Issue Analytics

  • State:open
  • Created 8 years ago
  • Reactions:1
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
gasmancommented, Sep 27, 2015

This is a result of #1571 - as of Wagtail 1.1, we set the ‘self’ and ‘page’ variables side by side (and use ‘page’ in the userbar logic) to accommodate the Jinja2 template engine, which doesn’t like us using the name ‘self’. We haven’t covered this in the documentation yet because full Jinja2 support is still in development.

To guard against changes like this, it’s probably best to use get_context rather than building your own context dictionary:

class CustomPage(Page):
    def serve(self, request, *args, **kwargs):
        return render(request, self.template, self.get_context(request))

and override get_context (using super) if you want to add extra variables there. We should update our documentation to demonstrate that pattern.

It would also be worth updating our userbar code to gracefully deal with the missing page variable though: if page is defined and refers to a page instance then use that, otherwise if self is defined and refers to a page instance then use that. @timheap, does that sound like it would work?

0reactions
rgantcommented, Feb 9, 2018

I was very happy with this logic:

@route(r'^tags/(?:(?P<tag>[-\w]+)/)?$')
def posts_by_tag(self, request, tag):
    """
    Display the index page filtered by a tag. If there is no tag for slug then redirect to the
    index.
    :param request: the current Django/Wagtail request object matching the tags route.
    :type request: django.core.handlers.wsgi.WSGIRequest
    :param str tag: This is the tagget Tag slug.
    :return: the result of Page.serve with our extra tag parameter.
    :rtype: django.template.response.TemplateResponse
    """
    try:
        tag_obj = Tag.objects.get(slug=tag)
    except Tag.DoesNotExist:
        if tag:
            msg = 'There are no blog posts tagged with "{}"'.format(tag)
            messages.add_message(request, messages.INFO, msg)
        return redirect(self.url)

    # Wagtail Page.serve will pass *args, **kwargs to both self.get_template & self.get_context
    return Page.serve(self, request, tag=tag_obj)

def get_context(self, request, *args, **kwargs):
    """
    Overrides the context to list all child items, that are live, by the date that they were
    published.

    This defines a Custom view that utilizes Tags. This view will return all related BlogPages
    for a given Tag or redirect back to the BlogIndexPage.

    http://docs.wagtail.io/en/latest/getting_started/tutorial.html#overriding-context
    :param request: the current Django/Wagtail request object
    :type request: django.core.handlers.wsgi.WSGIRequest
    :param taggit.models.Tag tag: optional tag to filter posts by.
    :return dict: context for template to render.
    """
    # Need to do it this way or pylint will complain about arguments-differ
    tag = kwargs.pop('tag', None)

    context = super().get_context(request, **kwargs)

    context['posts'] = self.paginate(request, tag)
    context['search_tag'] = tag

I think this is a better layout than the one used in bakerydemo because it uses the same get_context with and without a tag.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Context | Android Developers
MODE_MULTI_PROCESS does not work reliably in some versions of Android, ... For instance, a View associated with a restricted context would ignore particular ......
Read more >
Using mixins with class-based views - Django documentation
A common reason to override get_queryset() here would be to dynamically vary ... Not all mixins can be used together, and not all...
Read more >
Flutter get context in initState method - dart - Stack Overflow
What I'm trying to achieve is to check when the page is rendered to perform some checks and based on them opening a...
Read more >
Page models — Wagtail Documentation 4.1.1 documentation
get_url_parts(request) method will not typically be called directly, but may be overridden to define custom URL routing for a given page model. It...
Read more >
How To Use Contexts in Go - DigitalOcean
For example, if a web server function is handling an HTTP request for a ... You can use this as a placeholder when...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found