Is it bad practice to create wagtail page only for organizational purposes?

55 Views Asked by At

I am in the process of migrating an existing Django app for a news website over to Wagtail.

The first part of this migration will be porting all of the existing articles, that exist as Django models, over to Wagtail Pages.

Along with this, we will have separate Wagtail Page types for website pages such as terms and conditions, privacy policy, etc.

My question is the following, when looking that the Wagtail admin, it is clear that the articles need to be nested beneath a parent page for organizational purposes, otherwise all of the article pages will live amongst unrelated pages such as terms and conditions, privacy policy, etc...

I have thus created a basic Page which is used only for organizational purposes, it is the parent for all Articles and lives at the HomePage level.

class ArticleListing(Page):
    """A page meant for organizational purposes. All articles live under this page."""
    max_count = 1
    parent_page_types = ['news.HomePage']
    subpage_types = ['news.Article']

The problem is that in order to register this page, it is given a url path. I do not want to return anything from this page at all, the url related to it should throw a 404. What should I do here? I am thinking about overriding the route method to return a 404.

Is this a perversion of the Wagtail framework? If so how exactly am I supposed to organize my content within the Wagtail admin without having a giant mix of unrelated pages with no organization?

This same problem thus applies to the HomePage model I am using, which again is purely for organizational purposes at this stage in the migration.

class Index(Page):
    max_count = 1
2

There are 2 best solutions below

3
cnk On

We created a page type we called "MenuOnlyPage" so that people could add sections to their site without having to have content for the section index page. I don't love it but it is pretty popular.

class MenuOnlyPage(BasePage):
"""
This page exists purely to be a parent of other pages.  It has no content of its own, and the menu
behaves differently for these pages.

Rather than acting like a normal page, MenuOnlyPages always redirect to / if browsed to.
"""

###################
# EDIT FORM CONFIG
###################
content_panels = Page.content_panels + [
]

settings_panels = [
    MultiFieldPanel(
        heading='Page Settings',
        children=[
            FieldPanel('slug', widget=SlugInput),
            FieldPanel('nav_title'),
            FieldPanel('breadcrumb_title'),
            FieldPanel('show_in_menus'),
        ]
    )
]

publishing_panels = [
    PublishingPanel()
]

edit_handler = TabbedInterface(
    base_form_class=ShowInMenusByDefaultForm,
    children=[
        ObjectList(content_panels, heading='Content'),
        ObjectList(settings_panels, heading='Settings', classname='settings'),
        ObjectList(publishing_panels, heading='Publishing'),
    ]
)

# This should not appear in the search index.
search_fields = []

# This attribute is what the template code looks for to detect a MenuOnlyPage. Since only the template code cares
# about the difference, this is the easiest way to do it.
menu_only = True

page_description = 'Creates an entry in the Menu that exists only to be the parent of other Pages in the menu.'

class Meta:
    verbose_name = 'Menu-only Page'
    verbose_name_plural = 'Menu-only Pages'

def get_sitemap_urls(self, request=None):
    """
    Excludes all MenuOnlyPages from the XML Sitemap.
    """
    return []

@property
def preview_modes(self):
    """
    Disable previewing of MenuOnlyPages, since they don't have anything to preview.
    """
    return []

@property
def is_linkable(self):
    """
    Our breadcrumbs template uses this to know whether or not to create a link to this page.
    """
    return False

def serve(self, request, *args, **kwargs):
    """
    Rather than acting like a normal page, MenuOnlyPages always redirect to the homepage if browsed to.
    """
    # A user being able to visit one of these pages at all is a fluke, so we don't want to accidentally cache a
    # permanent redirect into their browser if they do manage to hit this code.
    response = redirect('/')
    return self.add_cache_control_headers(response)
0
Chathura Abeywickrama On

you can override the serve method to raise a 404 error. This way, when someone tries to access the URL associated with that page, a 404 response will be returned.

from django.http import Http404

class ArticleListing(Page):
    max_count = 1
    parent_page_types = ['news.HomePage']
    subpage_types = ['news.Article']

    def serve(self, request, *args, **kwargs):
        raise Http404