Ajouter une action sur un type de page uniquement avec wagtail

Wagtail permet de customiser à souhait son interface, il est possible de rajouter une action sur un type de page spécifique.

On suppose qu’on dispose du modèle EventPage, héritant de Page:

  # models.py
  from wagtail.core.models import Page

  class EventPage(Page):
      pass

Pour rajouter une action, celle-ci s’encode dans le fichier wagtail_hooks.py.

On crée une classe héritant de ActionMenuItem, et qui renverra une url.

  # wagtail_hooks.py
  from django.shortcuts import redirect
  from wagtail.admin.action_menu import ActionMenuItem
  class ShowEvent(ActionMenuItem):
      name = "show-event"
      label = _("Modifier le stage")
      icon_name = "edit"

      def get_url(self, request, context):
          return redirect("my_url_name")

Définir le classe ne suffit pas, il faut la rajouter à la liste des action_menu:

  # wagtail_hooks.py
  from wagtail.core import hooks
  @hooks.register("register_page_action_menu_item")
  def register_show_event_menu_item():
      return ShowEvent(order=10)

Le problème est que l’action apparaît sur toutes les pages, on va modifier ce comportement via le hooks construct_page_action_menu: on filtre la liste de menu_items, on n’affiche que ceux dont le nom n’est pas show-event, qui est le nom de notre classe ShowEvent définie plus haut.

  # wagtail_hooks.py
  @hooks.register("construct_page_action_menu")
  from .models import EventPage
  def show_event_only_on_event_page(menu_items, request, context):
      page = context.get("page")
      if not isinstance(page, EventPage):
          menu_items[:] = [item for item in menu_items if item.name != "show-event"]