Learn Wagtail CMS Course

Custom Admin Tabs

Let's say you have a too many fields on a Wagtail Page, and you want to organize the common fields. One option is to put your related fields in a MultiFieldPanel (ie. all your page banner settings) or if you have more you can create your own custom tab, like what you see below:

custom_tabs_wagtail.png

An example of a custom admin tab

To make this happen is really easy. There are 3 things you'll need:

  1. A TabbedInterface (It's just an import, really)
  2. An ObjectList (Create's the tab, and only takes a list)
    1. A list of panels you want to display

Let's take a look at some code.

Code for Custom Admin Tabs

This can all be done in one file, so you might just want to read the code below line-by-line.

from django.db import models
from wagtail.admin.edit_handlers import (
    FieldPanel,
    MultiFieldPanel,
    StreamFieldPanel,
    PageChooserPanel,
    ObjectList,
    TabbedInterface,
)
from wagtail.core.models import Page
from wagtail.core.fields import RichTextField, StreamField
from wagtail.images.edit_handlers import ImageChooserPanel
from streams import blocks


class HomePage(Page):
    """Home page model."""

    template = "home/home_page.html"
    subpage_types = [
        # ...
    ]
    parent_page_type = [
        'wagtailcore.Page'
    ]

    banner_title = models.CharField(max_length=100, blank=False, null=True)
    banner_subtitle = RichTextField(features=["bold", "italic"])
    banner_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    banner_cta = models.ForeignKey(
        "wagtailcore.Page",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    streamfields = StreamField([
        ("cta", blocks.CTABlock()),
    ], null=True, blank=True)

    content_panels = Page.content_panels + [
        StreamFieldPanel("streamfields"),
    ]

    # Custom list of panels. We'll put this in an ObjectList later.
    banner_panels = [
        MultiFieldPanel(
            [
                FieldPanel("banner_title"),
                FieldPanel("banner_subtitle"),
                ImageChooserPanel("banner_image"),
                PageChooserPanel("banner_cta"),
            ],
            heading="Banner Options",
        ),
    ]

    # This is where all the tabs are created
    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading='Content'),
            # This is our custom banner_panels. It's just a list, how easy!
            ObjectList(banner_panels, heading="Banner Settings"),
            ObjectList(Page.promote_panels, heading='Promotional Stuff'),
            ObjectList(Page.settings_panels, heading='Settings Stuff'),
        ]
    )

    class Meta:  # noqa

        verbose_name = "Home Page"
        verbose_name_plural = "Home Pages"

Just some light reading. Most of the above code isn't related, it just fills out the HomePage model a bit more so it looks more realistic. The parts you want to read are:

  • The imports (namely the ObjectList and TabbedInterface)
  • The banner_panels, and
  • The edit_handler

Essentially all we did was:

  1. Import new goodies
  2. Create a list of panels (banner_panels)
  3. Overwrite the pages edit_handler (tabs)
  4. Injected our custom banner_panels into the middle of the default tabs.

And that's it! It's truly amazing how easy it is to customize your website or application with Wagtail CMS.

The Git Commit

All the code you need can be found above. But hey, if you want to see how it effects the project we're making in the Learn Wagtail course, check out the full commit at https://github.com/CodingForEverybody/learn-wagtail/commit/ea8561d0a4823b653b01130491ec75f7e47ed310