wagtailinvisiblewagtail-pageurl

How to create an invisible dummy page in Wagtail?


How can I create an invisible dummy page in Wagtail?

I need a "virtual" page object within Wagtail to build a menu for non Wagtail based pages and also external resources. (See my entry post here)

class MenuDummyPage(Page):

    menu_description    = models.CharField(max_length=255, blank=True)
    menu_icon           = models.CharField(max_length=255, blank=True)
    menu_link           = models.CharField(max_length=255, blank=True)

    settings_panels = [
        FieldPanel('menu_description'),
        FieldPanel('menu_icon'),
        FieldPanel('menu_link'),
    ]

    def get_sitemap_urls(self):
        return []

    def serve(self, request):
        pass

If I create the above page object then it is not listed within the generated wagtail sitemap.

But if I navigate on my own to that page manually the object is called. How can I stop this?

Example: If I create a MenuDummyPage with the title "This is a test" then the system will automatically generate a slug => "this-is-a-test".

If I call "/this-is-a-test"/ in my browser wagtail is answering because the slug exists. How can I remove this behavior for my "MenuDummyPage" objects?


Solution

  • If what you mean by a dummy page is a page under which other pages are kept in the page tree, then you could do the following:

    from django.http import HttpResponseRedirect
    
    class Node(Page):
    
        subpage_types = [your subpage types]
        parent_page_types = [your parent page types]
    
        link = models.CharField(max_length=255, default='', blank='True')
    
        content_panels = Page.content_panels + [
            FieldPanel('link')
        ]  
    
        def serve(self, request):
            if self.link is not None:
                return HttpResponseRedirect(self.link)
            # To handle the situation where someone inadvertantly lands on a parent page, do a redirect
            first_descendant = self.get_descendants().first()
            if first_descendant:
                return HttpResponseRedirect(first_descendant.url)
            else:
                return HttpResponseRedirect(request.site.root_page.url)
    

    The optional link field allows you to define a link if you wish for this position in the page tree structure. The above, again, assumes that you are using this Page-based item as a placeholder in the Page tree so that you can have other Pages under it. As long as you don't render the url of this page in your template, then users should never know how to get to the url for the Node, but if someone does get to the url for a Node-type page, then the first_descendant logic handles this situation by sending them to either the first descendant of the Node or to the home page if no descendants of Node exist.

    In your template (note the use of specific_class):

    {% for item in menu_items %}
        <li>
            <a href="{% if item.specific.link and item.specific.link != '' %}{{ item.specific.link }}{% elif item.specific_class == 'Node'%}#{% else %}{% pageurl item %}{% endif %}">{{ item.title }
            </a>
        </li>
    {% endfor %}