Philipp S.
Philipp S.

Reputation: 981

Group pages in wagtail

how can i group pages in wagtail cms?

I have a page model for cities in my project. Accessible throw /cityname/:

After having hundrets of cities in my database, my root view in wagtail cms got unclear. I would like to group all cities, how can i do this?

Usually you would create a parent object, but in this case my parent is the root. Can I create somehow a virtual parent page?

Upvotes: 1

Views: 1101

Answers (2)

Loïc Teixeira
Loïc Teixeira

Reputation: 1434

There are no such thing as a virtual parent page in Wagtail and I'm not sure whether you want all the cities pages to go under a single parent of have multiple parent (e.g. grouping cities by country or something). I'll assume the later but let me know if that's not the case and I'll update the answer.

So you have a few options here:

1) Create a CountryPage as a child of the Homepage and under which live all the CityPage. Then you accept that the url will be /france/paris/.

2) Create a CountryPage as a child of the Homepage and under which live all the CityPage (same as option 1), but you also make the Homepage a RoutablePage which will serve the content of the cities pages.

from django.shortcuts import get_object_or_404
from wagtail.wagtailcore.models import Page
from wagtail.contrib.wagtailroutablepage.models import RoutablePageMixin, route


class Homepage(RoutablePageMixin, Page):
    @route(r'^(\w+)/$', name='city')
    def city(self, request, city_slug):
        city = get_object_or_404(CityPage, slug=city_slug)
        return city.serve(request)

However this has some caveats: - The CityPage is still available at /france/paris/ so you'll need to setup the canonical URL to make sure there is no double indexing. - The CountryPage is still available at /france/ which you might not want. - The names might clash. For example, if you have a CountryPage with a slug of luxembourg with a CityPage of with the same slug as a child. When you'll visit /luxembourg/ you would expect the Homepage to pick it up and server /luxembourg/luxembourg/ but it won't because the URL will be picked up by the CountryPage at /luxembourg/ already.

3) If your cities don't necessarily need to be a page (they are more data holder than anything else and don't have children), you could convert them to a model. This model would be exposed in the admin interface as snippets or modeladmin and served by the Homepage (similarly to option 2).

from django.shortcuts import get_object_or_404, render
from wagtail.wagtailcore.models import Page
from wagtail.contrib.wagtailroutablepage.models import RoutablePageMixin, route


class Homepage(RoutablePageMixin, Page):
    @route(r'^(\w+)/$', name='city')
    def city(self, request, city_slug):
        city = get_object_or_404(CityModel, slug=city_slug)

        context = self.get_context(request, *args, **kwargs)
        context['city'] = city

        return render(request, 'city.html', context)

Upvotes: 0

LB Ben Johnston
LB Ben Johnston

Reputation: 5186

You cannot have a virtual parent page from within the Explorer section of the admin, you can only (currently) navigate/manage pages within their native tree structure.

However, you may want to use modeladmin to provide a separate section of the admin dedicated to editing the city pages. Using modelAdmin also lets you hide the city page type from the Explorer section and gives you lots of customisation on how pages are listed, searched and filtered.

Here is a slightly modified example from the docs.

# file: myapp/wagtail_hooks.py
from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register)
from .models import CityPage


class CityPageModelAdmin(ModelAdmin):
    model = CityPage
    menu_label = 'Cities'  # ditch this to use verbose_name_plural from model
    menu_icon = 'grip'  # change as required
    menu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)
    add_to_settings_menu = False  # or True to add your model to the Settings sub-menu
    exclude_from_explorer = True # setting to true will exclude pages of this type from Wagtail's explorer view
    list_display = ('title', 'country', 'other_example_field', 'live')
    list_filter = ('live', 'country')
    search_fields = ('title',) # remember trailing comma on single item sets

# Now you just need to register your customised ModelAdmin class with Wagtail
modeladmin_register(CityPageModelAdmin)

Upvotes: 1

Related Questions