Repository: wagtail/wagtail
File: wagtail/admin/views/generic/base.py (Python)

Code before:
from wagtail.admin.widgets.button import ButtonWithDropdown
from wagtail.search.backends import get_search_backend
from wagtail.search.index import class_is_indexed
from wagtail.utils.utils import flatten_choices


class WagtailAdminTemplateMixin(TemplateResponseMixin, ContextMixin):
    """
    Mixin for views that render a template response using the standard Wagtail admin
    page furniture.
    Provides accessors for page title, subtitle and header icon.
    """

    page_title = ""
    page_subtitle = ""
    header_icon = ""
    # Breadcrumbs are opt-in until we have a design that can be consistently applied
    _show_breadcrumbs = False
    breadcrumbs_items = [{"url": reverse_lazy("wagtailadmin_home"), "label": _("Home")}]
    template_name = "wagtailadmin/generic/base.html"
    header_buttons = []
    header_more_buttons = []

    def get_page_title(self):
        return self.page_title

    def get_page_subtitle(self):
        return self.page_subtitle

    def get_header_title(self):
        title = self.get_page_title()
        subtitle = self.get_page_subtitle()
        if subtitle:
            title = f"{title}: {subtitle}"
        return title

    def get_header_icon(self):
        return self.header_icon

    def get_breadcrumbs_items(self):
        return self.breadcrumbs_items

    def get_header_buttons(self):
        buttons = sorted(self.header_buttons)

        more_buttons = self.get_header_more_buttons()
        if more_buttons:
            buttons.append(
                ButtonWithDropdown(
                    buttons=more_buttons,
                    icon_name="dots-horizontal",

Review comment (refactor):
We probably should name this `base_breadcrumbs_items` instead. I initially only followed the existing patterns for `page_title`, `page_subtitle`, and `header_icon` having their respective `get_foo` methods.

I wasn't sure how the API would eventually take shape once we migrated all the views and made the page views use the same mechanism. I think it's starting to stabilise – but the role of the `breadcrumbs_items` list is more like the base items that can be easily overridden from a higher abstraction e.g. `SnippetViewSet` to provide the "Snippets" menu item, while the actual view defines the path to itself in the `get_breadcrumbs_items()` method.

Code after:
from wagtail.admin.widgets.button import ButtonWithDropdown
from wagtail.search.backends import get_search_backend
from wagtail.search.index import class_is_indexed
from wagtail.utils.utils import flatten_choices


class WagtailAdminTemplateMixin(TemplateResponseMixin, ContextMixin):
    """
    Mixin for views that render a template response using the standard Wagtail admin
    page furniture.
    Provides accessors for page title, subtitle and header icon.
    """

    page_title = ""
    page_subtitle = ""
    header_icon = ""

    breadcrumbs_items = [{"url": reverse_lazy("wagtailadmin_home"), "label": _("Home")}]
    """
    The base set of breadcrumbs items to be displayed on the page.
    The property can be overridden by subclasses and viewsets to provide
    custom base items, e.g. page tree breadcrumbs or add the "Snippets" item.

    Views should copy and append to this list in :meth:`get_breadcrumbs_items()`
    to define the path to the current view.
    """

    template_name = "wagtailadmin/generic/base.html"
    header_buttons = []
    header_more_buttons = []

    def get_page_title(self):
        return self.page_title

    def get_page_subtitle(self):
        return self.page_subtitle

    def get_header_title(self):
        title = self.get_page_title()
        subtitle = self.get_page_subtitle()
        if subtitle:
            title = f"{title}: {subtitle}"
        return title

    def get_header_icon(self):
        return self.header_icon

    def get_breadcrumbs_items(self):
        """
        Define the current path to the view by copying the base
        :attr:`breadcrumbs_items` and appending the list.