FlipperPA
FlipperPA

Reputation: 14311

Wagtail: render a page programmatically in a Class Based View

I've got a Wagtail setting where a user can select a page to render, and if it is not set, it returns a listing page using ListView of recent posts. Here is the setting:

@register_setting
class PeregrineSettings(BaseSetting):
    """
    Settings for the user to customize their Peregrine blog.
    """
    landing_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        help_text='The page to display at the root. If blank, displays the latest posts.'
    )

The setting works. When I try to use it in the ListView, I'm attempting to pass the url_path to Wagtail's serve method, but it doesn't render the page view; I get a 404. Here's the code of the ListView:

class PostsListView(ListView):
    """
    Paginated view of blog posts.
    """
    model = SitePost
    template_name = 'peregrine/site_post_list.html'
    context_object_name = 'posts'
    paginate_by = 10
    ordering = ['-post_date']

    def get(self, request, *args, **kwargs):
        peregrine_settings = PeregrineSettings.for_site(request.site)
        if peregrine_settings.landing_page is None:
            # Render list of recent posts
            response = super().get(request, *args, **kwargs)
            return response
        else:
            # Render landing page
            return serve(request, peregrine_settings.landing_page.url_path)

It feels like I'm missing a way to just pass the Page instance stored in peregrine_settings.landing_page to a method to render. Can anyone shed some light on the internals at work here? Thank you!

Upvotes: 0

Views: 1310

Answers (1)

gasman
gasman

Reputation: 25227

I take it the serve function you're calling here is the view defined in wagtail.core.views? This view doesn't do much by itself - it calls route() on the site root page to locate the correct page, then calls that page's serve() method (passing the request object) to do the actual page rendering. It looks like this latter serve() method is what you need:

def get(self, request, *args, **kwargs):
    peregrine_settings = PeregrineSettings.for_site(request.site)
    if peregrine_settings.landing_page is None:
        # ...
    else:
        # Render landing page
        return peregrine_settings.landing_page.serve(request)

Some further documentation about the route and serve methods can be found here: http://docs.wagtail.io/en/v2.0/reference/pages/theory.html#anatomy-of-a-wagtail-request http://docs.wagtail.io/en/v2.0/reference/pages/model_recipes.html#overriding-the-serve-method

Upvotes: 3

Related Questions