<a id="custom-page-listings"></a>

# Customizing page listings

<a id="custom-default-page-listings"></a>

## Customizing the default page listings

#### Versionadded
Added in version 7.4: The ability to customize the page explorer listing was added.

The page explorer is the default listing of pages in the Wagtail admin, where editors can navigate through the structure of the page tree. The pages in the tree can be of different types, thus only a limited set of fields common to all pages are available for display, filtering, and ordering. Wagtail provides a default set of columns and filters for the page explorer, but you may want to customize them to cater to your editors’ needs.

To customize the default page explorer listing, create a subclass of [`PageViewSet`](../../reference/viewsets.md#wagtail.admin.viewsets.pages.PageViewSet) and register it using the [`register_admin_viewset`](../../reference/hooks.md#register-admin-viewset) hook. For example, to add a column for the `slug` field on all page listings, you could override the [`columns`](../../reference/viewsets.md#wagtail.admin.viewsets.pages.PageViewSet.columns) attribute on the viewset to add a new [`Column`](../../reference/ui/tables.md#wagtail.admin.ui.tables.Column) instance, and then register the viewset in a `wagtail_hooks.py` file within the app as follows:

```python
# myapp/wagtail_hooks.py
from wagtail import hooks
from wagtail.admin.ui.tables import Column
from wagtail.admin.viewsets.pages import PageViewSet
from wagtail.models import Page


class CustomPageViewSet(PageViewSet):
    columns = PageViewSet.columns + [
        Column("slug", label="Slug", sort_key="slug"),
    ]


custom_page_viewset = CustomPageViewSet()
@hooks.register("register_admin_viewset")
def register_custom_page_viewset():
    return custom_page_viewset
```

The filtering options for the listing can be customized by overriding the `filterset_class` attribute on the viewset. For example, you could add a filter for the `slug` field as follows:

```python
from wagtail import hooks
from wagtail.admin.viewsets.pages import PageViewSet
from wagtail.models import Page


class CustomPageFilterSet(PageViewSet.filterset_class):
    class Meta:
        model = Page
        fields = ["slug"]


class CustomPageViewSet(PageViewSet):
    # ...
    filterset_class = CustomPageFilterSet
```

For some page types, you may have enforced that only a single page type can be created under a given parent page. For example, your site may implement a `BlogIndexPage` model with its [`subpage_types`](../../reference/models.md#wagtail.models.Page.subpage_types) set to only allow `BlogPage` instances under it. With the listing limited to `BlogPage` instances, you can display, filter, and order on additional fields specific to `BlogPage` when viewing the children of a `BlogIndexPage`.

To customize the page explorer listing for a given parent page, set the `model` and `parent_models` attributes on a custom `PageViewSet` subclass. The following is an example of a custom viewset that adds a column and a filter for the `blog_category` field on the listing of `BlogPage` instances under a `BlogIndexPage`:

```python
# myapp/wagtail_hooks.py
from wagtail import hooks
from wagtail.admin.ui.tables import Column
from wagtail.admin.viewsets.pages import PageViewSet

from myapp.models import BlogIndexPage, BlogPage


class BlogPageFilterSet(PageViewSet.filterset_class):
    class Meta:
        model = BlogPage
        fields = ["blog_category"]


class BlogPageViewSet(PageViewSet):
    model = BlogPage
    parent_models = [BlogIndexPage]
    columns = PageViewSet.columns + [
        Column("blog_category", label="Category", sort_key="blog_category"),
    ]
    filterset_class = BlogPageFilterSet


blog_page_viewset = BlogPageViewSet()
@hooks.register("register_admin_viewset")
def register_blog_page_viewset():
    return blog_page_viewset
```

Normally, editors navigate through the Wagtail admin interface by following the structure of the page tree. However, this can make it slow to locate a specific page for editing, especially on large sites where pages are organised into a deep hierarchy.

By default, Wagtail also provides a flat listing for each page type that can be accessed from the page types usage report. If you have registered a custom `PageViewSet` to customize the page explorer listing for a specific page type (as described in the above section), then all customizations you have made will also be applied to the flat listing for that page type.

Various other options are available for customizing the page listings, such as the `list_per_page` attribute to control how many items are shown per page, and the `ordering` attribute to control the default ordering of items in the listing. See the documentation for [`PageViewSet`](../../reference/viewsets.md#wagtail.admin.viewsets.pages.PageViewSet) for more details.

<a id="custom-flat-page-listings"></a>

## Creating custom flat page listings

In addition to the default page explorer and flat per-page-type listings, you can also create your own custom flat listings of all pages of a given type. This custom listing can be accessed from a menu item in the Wagtail admin menu, with the ability for editors to search and filter this list to find the pages they are interested in. To define a custom page listing, create a subclass of [`PageListingViewSet`](../../reference/viewsets.md#wagtail.admin.viewsets.pages.PageListingViewSet) and register it using the [`register_admin_viewset`](../../reference/hooks.md#register-admin-viewset) hook.

For example, if your site implemented the page type `BlogPage`, you could provide a “Blog pages” listing in the Wagtail admin by adding the following definitions to a `wagtail_hooks.py` file within the app:

```python
# myapp/wagtail_hooks.py
from wagtail import hooks
from wagtail.admin.viewsets.pages import PageListingViewSet

from myapp.models import BlogPage


class BlogPageListingViewSet(PageListingViewSet):
    icon = "globe"
    menu_label = "Blog Pages"
    add_to_admin_menu = True
    model = BlogPage


blog_page_listing_viewset = BlogPageListingViewSet("blog_pages")
@hooks.register("register_admin_viewset")
def register_blog_page_listing_viewset():
    return blog_page_listing_viewset
```

The columns of the listing can be customized by overriding the `columns` attribute on the viewset. This should be a list of [`Column`](../../reference/ui/tables.md#wagtail.admin.ui.tables.Column) instances:

```python
from wagtail import hooks
from wagtail.admin.ui.tables import Column
from wagtail.admin.viewsets.pages import PageListingViewSet

from myapp.models import BlogPage

class BlogPageListingViewSet(PageListingViewSet):
    # ...
    columns = PageListingViewSet.columns + [
        Column("blog_category", label="Category", sort_key="blog_category"),
    ]
```

The filtering options for the listing can be customized by overriding the `filterset_class` attribute on the viewset:

```python
from wagtail import hooks
from wagtail.admin.viewsets.pages import PageListingViewSet

from myapp.models import BlogPage


class BlogPageFilterSet(PageListingViewSet.filterset_class):
    class Meta:
        model = BlogPage
        fields = ["blog_category"]


class BlogPageListingViewSet(PageListingViewSet):
    # ...
    filterset_class = BlogPageFilterSet
```
