Spec-Zone.ru › Wagtail

Обработчики

При загрузке Wagtail будет искать любой приложение с файлом wagtail_hooks.py и выполнять его содержимое. Это предоставляет способ зарегистрировать собственные функции для выполнения в определенные моменты выполнения Wagtail, например, при сохранении страницы или при построении основного меню.

Примечание

Обработчики обычно используются для настройки поведения на уровне отображения Wagtail админки и фронтенда. Для настроек, которые связаны только с поведением на уровне модели - например, для вызова внешнего сервиса при добавлении страницы или документа - часто лучше использовать механизм сигналов Django механизм сигналов Django (см. также: Сигналы Wagtail), так как они не зависят от того, проходит ли пользователь определенный путь через админский интерфейс.

Регистрация функций с помощью обработчика Wagtail выполняется с помощью декоратора @hooks.register:

from wagtail import hooks

@hooks.register('name_of_hook')
def my_hook_function(arg1, arg2...)
    # your code here

В качестве альтернативы, можно вызвать hooks.register как обычную функцию, передав имя обработчика и функцию-обработчик, определенную в другом месте:

hooks.register('name_of_hook', my_hook_function)

Если вам нужно, чтобы ваши обработчики выполнялись в определенном порядке, вы можете передать параметр order. Если порядок не указан, обработчики выполняются в порядке, заданном INSTALLED_APPS. Wagtail также использует обработчики внутри себя, поэтому при переопределении встроенных функций Wagtail необходимо учитывать порядок (например, при удалении элементов сводки по умолчанию):

@hooks.register('name_of_hook', order=1)  # This will run after every hook in the wagtail core
def my_hook_function(arg1, arg2...)
    # your code here

@hooks.register('name_of_hook', order=-1)  # This will run before every hook in the wagtail core
def my_other_hook_function(arg1, arg2...)
    # your code here

@hooks.register('name_of_hook', order=2)  # This will run after `my_hook_function`
def yet_another_hook_function(arg1, arg2...)
    # your code here

Тестирование обработчиков

Обработчики обычно регистрируются при запуске и не могут быть изменены во время выполнения. Но при написании unit-тестов вам, возможно, захочется зарегистрировать функцию-обработчик только для одного теста или блока кода и отменить её регистрацию, чтобы она не выполнялась при запуске других тестов.

Вы можете временно зарегистрировать обработчики, используя функцию hooks.register_temporarily, которая может использоваться как декоратор, так и контекстный менеджер. Вот пример того, как зарегистрировать функцию-обработчик только для одного теста:

def my_hook_function():
    pass

class MyHookTest(TestCase):

    @hooks.register_temporarily('name_of_hook', my_hook_function)
    def test_my_hook_function(self):
        # Test with the hook registered here
        pass

А вот пример регистрации функции-обработчика для одного блока кода:

def my_hook_function():
    pass

with hooks.register_temporarily('name_of_hook', my_hook_function):
    # Hook is registered here
    ..

# Hook is unregistered here

Если вам нужно зарегистрировать несколько обработчиков в блоке with, вы можете передать их как список кортежей:

def my_hook(...):
    pass

def my_other_hook(...):
    pass

with hooks.register_temporarily([
    ('hook_name', my_hook),
    ('hook_name', my_other_hook),
]):
    # All hooks are registered here
    ..

# All hooks are unregistered here

Доступные обработчики перечислены ниже.

Модули администрирования

Фиксаторы для создания новых областей админ-интерфейса (наряду со страницами, изображениями, документами и так далее).

construct_homepage_panels

Добавить или удалить панели с главной страницы Wagtail админки. Передаваемая в этот фиксатор вызываемая функция должна принять объект request и список объектов панели, и должна изменить этот список по мере необходимости. Объекты панели являются Шаблонными компонентами с дополнительным свойством order, целым числом, определяющим позицию панели в окончательном отсортированном списке. Панели по умолчанию используют целые числа между 100 и 300.

from django.utils.safestring import mark_safe

from wagtail.admin.ui.components import Component
from wagtail import hooks

class WelcomePanel(Component):
    order = 50

    def render_html(self, parent_context):
        return mark_safe("""
        <section class="panel summary nice-padding">
          <h3>No, but seriously -- welcome to the admin homepage.</h3>
        </section>
        """)

@hooks.register('construct_homepage_panels')
def add_another_welcome_panel(request, panels):
    panels.append(WelcomePanel())

construct_homepage_summary_items

Добавить или удалить элементы из панели «Краткое описание сайта» на главной странице админки (которая отображает количество страниц и других объектов, существующих на сайте). Передаваемая в этот фиксатор вызываемая функция должна принять объект request и список объектов элемента краткого описания, и должна изменить этот список по мере необходимости. Объекты элемента краткого описания являются экземплярами wagtail.admin.site_summary.SummaryItem, который расширяет класс Component следующими дополнительными методами и свойствами:

construct_main_menu

Вызывается непосредственно перед выводом меню Wagtail админки, чтобы позволить изменить список элементов меню. Передаваемая в этот фиксатор вызываемая функция получит объект request и список menu_items, и должна изменить menu_items по мере необходимости. Добавление элементов меню обычно выполняется через фиксатор register_admin_menu_item вместо этого — элементы, добавленные через construct_main_menu, не будут проверять свое is_shown.

from wagtail import hooks

@hooks.register('construct_main_menu')
def hide_explorer_menu_item_from_frank(request, menu_items):
  if request.user.username == 'frank':
    menu_items[:] = [item for item in menu_items if item.name != 'explorer']

describe_collection_contents

Вызывается, когда Wagtail нужно узнать, какие объекты существуют в коллекции, если таковые есть. В настоящее время это происходит при подтверждении перед удалением коллекции, чтобы убедиться, что пустые коллекции не могут быть удалены. Передаваемая в этот фиксатор вызываемая функция получит объект collection и должна вернуть либо None (чтобы указать отсутствие объектов в этой коллекции), либо словарь, содержащий следующие ключи:

  • count - числовое количество элементов в этой коллекции
  • count_text - удобочитаемая строка, описывающая количество элементов в этой коллекции, например, «3 документа». (В сайтах с поддержкой нескольких языков здесь следует вернуть переводимую строку, скорее всего, используя функцию django.utils.translation.ngettext.)
  • url (необязательно) - URL страницы индекса, которая перечисляет описываемые объекты.

register_account_settings_panel

Регистрирует новый класс панели настроек для добавления в представление «Аккаунт» в админке.

Этот фиксатор может быть добавлен в подкласс BaseSettingsPanel. Например:

from wagtail.admin.views.account import BaseSettingsPanel
from wagtail import hooks

@hooks.register('register_account_settings_panel')
class CustomSettingsPanel(BaseSettingsPanel):
    name = 'custom'
    title = "My custom settings"
    order = 500
    form_class = CustomSettingsForm

В качестве альтернативы, он также может быть добавлен в функцию. Например, эта функция эквивалентна вышеприведенной:

from wagtail.admin.views.account import BaseSettingsPanel
from wagtail import hooks

class CustomSettingsPanel(BaseSettingsPanel):
    name = 'custom'
    title = "My custom settings"
    order = 500
    form_class = CustomSettingsForm

@hooks.register('register_account_settings_panel')
def register_custom_settings_panel(request, user, profile):
    return CustomSettingsPanel(request, user, profile)

Дополнительные сведения о доступных параметрах можно найти в Настройка формы настроек учетной записи пользователя.

register_account_menu_item

Добавляет элемент на вкладку «Дополнительные действия» на странице «Аккаунт» в админке Wagtail. Вызываемая функция для этого фиксатора должна вернуть словарь с ключами url, label и help_text. Например:

from django.urls import reverse
from wagtail import hooks

@hooks.register('register_account_menu_item')
def register_account_delete_account(request):
    return {
        'url': reverse('delete-account'),
        'label': 'Delete account',
        'help_text': 'This permanently deletes your account.'
    }

register_admin_menu_item

Добавляет элемент в меню Wagtail админки. Передаваемая в этот фиксатор вызываемая функция должна вернуть экземпляр wagtail.admin.menu.MenuItem. Новые элементы могут быть созданы из класса MenuItem, передавая в него label, который будет текстом в элементе меню, и URL страницы админки, к которой вы хотите связать элемент меню (обычно вызывая reverse() на представлении админки, которое вы настроили). Кроме того, принимаются следующие ключевые аргументы:

  • name - внутреннее имя, используемое для идентификации элемента меню; по умолчанию соответствует slugified форме метки.
  • icon_name - иконка для отображения рядом с элементом меню; без значений по умолчанию, необязательно, но должна быть установлена для элементов верхнего уровня меню, чтобы их можно было идентифицировать при свернутом состоянии.
  • classnames - дополнительные имена классов, применяемые к ссылке
  • order - целое число, определяющее позицию элемента в меню

Для элементов меню, доступных только суперпользователям, можно использовать подкласс wagtail.admin.menu.AdminOnlyMenuItem вместо MenuItem.

MenuItem можно далее наследовать, чтобы настроить его инициализацию или условно отображать или скрывать элемент для определенных запросов (например, для применения проверок разрешений); см. исходный код (wagtail/admin/menu.py) для получения подробностей.

from django.urls import reverse

from wagtail import hooks
from wagtail.admin.menu import MenuItem

@hooks.register('register_admin_menu_item')
def register_frank_menu_item():
  return MenuItem('Frank', reverse('frank'), icon_name='folder-inverse', order=10000)

register_admin_urls

Регистрация дополнительных URL-адресов страниц админки. Вызываемая функция, переданная в этот фиксатор, должна вернуть список шаблонов Django URL, которые определяют структуру страниц и конечных точек вашего расширения для админки Wagtail. Более подробную информацию о стандартных Django URLconf и представлениях см. в диспетчере URL-адресов.

from django.http import HttpResponse
from django.urls import path

from wagtail import hooks

def admin_view(request):
  return HttpResponse(
    "I have approximate knowledge of many things!",
    content_type="text/plain")

@hooks.register('register_admin_urls')
def urlconf_time():
  return [
    path('how_did_you_almost_know_my_name/', admin_view, name='frank'),
  ]

register_group_permission_panel

Добавление новой панели в форму «Группы» в области «Настройки». Передаваемая в этот фиксатор вызываемая функция должна вернуть класс ModelForm/ModelFormSet, с конструктором, который принимает объект группы в качестве ключевого аргумента instance и который реализует методы save, is_valid и as_admin_panel (который возвращает HTML для включения на странице редактирования группы).

register_settings_menu_item

Как register_admin_menu_item, но регистрирует элементы меню в подменю «Настройки», а не в главном меню.

construct_settings_menu

Как construct_main_menu, но изменяет подменю «Настройки», а не главное меню.

register_reports_menu_item

Как register_admin_menu_item, но регистрирует элементы меню в подменю «Отчеты», а не в главном меню.

construct_reports_menu

Как construct_main_menu, но изменяет подменю «Отчеты», а не главное меню.

register_help_menu_item

Как register_admin_menu_item, но регистрирует элементы меню в подменю «Помощь», а не в главном меню.

construct_help_menu

Как construct_main_menu, но изменяет подменю «Помощь», а не главное меню.

register_admin_search_area

Добавление элемента в поиск Wagtail админки «Другие поиски». Поведение этого фиксатора аналогично register_admin_menu_item. Передаваемая в этот фиксатор вызываемая функция должна вернуть экземпляр wagtail.admin.search.SearchArea. Новые элементы могут быть созданы из класса SearchArea, передавая следующие параметры:

  • label - текст, отображаемый в поле «Другие поиски».
  • name - внутреннее имя, используемое для идентификации варианта поиска; по умолчанию соответствует slugified форме метки.
  • url - URL целевой страницы поиска.
  • classnames - произвольные имена CSS-классов, применяемые к ссылке
  • icon_name - иконка для отображения рядом с меткой.
  • attrs - дополнительные HTML-атрибуты для применения к ссылке.
  • order - целое число, определяющее позицию элемента в списке вариантов.

Установка URL может быть достигнута с помощью reverse() на целевой странице поиска. Параметр GET ‘q’ будет добавлен к заданному URL.

В шаблоне предоставлена метка search_other модулем шаблонов wagtailadmin_tags. Эта метка принимает один необязательный параметр current, который позволяет указать name варианта поиска, который в данный момент активен. Если параметр не указан, фиксатор по умолчанию выполняет обратный поиск URL страницы для сравнения с параметром url.

SearchArea можно унаследовать, чтобы настроить вывод HTML, указать необходимые JavaScript-файлы, или условно отображать или скрывать элемент для определенных запросов (например, для применения проверок разрешений); см. исходный код (wagtail/admin/search.py) для получения подробностей.

from django.urls import reverse
from wagtail import hooks
from wagtail.admin.search import SearchArea

@hooks.register('register_admin_search_area')
def register_frank_search_area():
    return SearchArea('Frank', reverse('frank'), icon_name='folder-inverse', order=10000)

register_permissions

Возвращает QuerySet объектов Permission, которые необходимо отобразить в области администрирования «Группы».

  from django.contrib.auth.models import Permission
  from wagtail import hooks


  @hooks.register('register_permissions')
  def register_permissions():
      app = 'blog'
      model = 'extramodelset'

      return Permission.objects.filter(content_type__app_label=app, codename__in=[
          f"view_{model}", f"add_{model}", f"change_{model}", f"delete_{model}"
      ])

filter_form_submissions_for_user

Позволяет настраивать доступ к отправленным формам на основе пользователя и формы.

Этот фиксатор принимает два параметра:

  • Пользователь, пытающийся получить доступ к отправкам форм
  • Список страниц форм QuerySet

Фиксатор должен вернуть QuerySet, содержащий подмножество этих страниц форм, к которым пользователю разрешен доступ к отправкам.

Например, чтобы предотвратить доступ не-суперпользователей к отправкам форм:

from wagtail import hooks


@hooks.register('filter_form_submissions_for_user')
def construct_forms_for_user(user, queryset):
    if not user.is_superuser:
        queryset = queryset.none()

    return queryset

Интерфейс редактора

Обработчики для настройки интерфейса редактирования страниц и фрагментов.

register_rich_text_features

Поля rich text в Wagtail работают со списком идентификаторов «функций», которые определяют, какие элементы управления редактированием доступны в редакторе и какие элементы разрешены в выводе; например, поле rich text, определённое как RichTextField(features=['h2', 'h3', 'bold', 'italic', 'link']), позволит использовать заголовки, форматирование полужирным/курсивом и ссылки, но не (например) маркированные списки или изображения. Обработчик register_rich_text_features позволяет определять новые идентификаторы функций — см. Ограничение функций в поле rich text для получения подробной информации.

insert_editor_css

Добавление дополнительных файлов CSS или фрагментов в редактор страницы.

from django.templatetags.static import static
from django.utils.html import format_html

from wagtail import hooks

@hooks.register('insert_editor_css')
def editor_css():
    return format_html(
        '<link rel="stylesheet" href="{}">',
        static('demo/css/vendor/font-awesome/css/font-awesome.min.css')
    )

insert_global_admin_css

Добавление дополнительных файлов CSS или фрагментов кода на все страницы админки.

from django.utils.html import format_html
from django.templatetags.static import static

from wagtail import hooks

@hooks.register('insert_global_admin_css')
def global_admin_css():
    return format_html('<link rel="stylesheet" href="{}">', static('my/wagtail/theme.css'))

insert_editor_js

Добавление дополнительных файлов JavaScript или фрагментов кода в редактор страницы.

from django.utils.html import format_html_join
from django.utils.safestring import mark_safe
from django.templatetags.static import static

from wagtail import hooks

@hooks.register('insert_editor_js')
def editor_js():
    js_files = [
        'js/fireworks.js', # https://fireworks.js.org
    ]
    js_includes = format_html_join('\n', '<script src="{0}"></script>',
        ((static(filename),) for filename in js_files)
    )
    return js_includes + mark_safe(
        """
        <script>
            window.addEventListener('DOMContentLoaded', (event) => {
                var container = document.createElement('div');
                container.style.cssText = 'position: fixed; width: 100%; height: 100%; z-index: 100; top: 0; left: 0; pointer-events: none;';
                container.id = 'fireworks';
                document.getElementById('main').prepend(container);
                var options = { "acceleration": 1.2, "autoresize": true, "mouse": { "click": true, "max": 3 } };
                var fireworks = new Fireworks(document.getElementById('fireworks'), options);
                fireworks.start();
            });
        </script>
        """
    )

insert_global_admin_js

Добавление дополнительных файлов JavaScript или фрагментов кода на все страницы админки.

from django.utils.safestring import mark_safe

from wagtail import hooks

@hooks.register('insert_global_admin_js')
def global_admin_js():
    return mark_safe(
        '<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.js"></script>',
    )

register_page_header_buttons

Добавление кнопок во вспомогательное выпадающее меню в заголовке страницы. Это работает аналогично обработчику register_page_listing_buttons.

Этот пример добавит простую кнопку во вспомогательное выпадающее меню:

from wagtail.admin import widgets as wagtailadmin_widgets

@hooks.register('register_page_header_buttons')
def page_header_buttons(page, page_perms, next_url=None):
    yield wagtailadmin_widgets.Button(
        'A dropdown button',
        '/goes/to/a/url/',
        priority=60
    )

Аргументы, передаваемые обработчику, следующие:

  • page — объект страницы, для которой генерируется кнопка
  • page_perms — объект PagePermissionTester, который можно запросить для определения разрешений текущего пользователя на данной странице
  • next_url — URL, к которому должна перенаправить связанное действие при завершении действия, если представление его поддерживает

Аргумент priority управляет порядком отображения кнопок в выпадающем меню. Кнопки упорядочены от низкого к высокому приоритету, поэтому кнопка с priority=10 будет отображаться перед кнопкой с priority=60.

Рабочий процесс редактора

Фишки для настройки способа навигации пользователей по процессу создания контента страницы.

after_create_page

Выполните какие-либо действия с объектом Page после его сохранения в базе данных (в качестве опубликованной страницы или пересмотра). Передаваемая в эту фишку вызываемая функция должна принимать объект request и объект page. Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа. По умолчанию Wagtail перенаправит пользователя на страницу «Обзор» для родительской страницы новой страницы.

from django.http import HttpResponse

from wagtail import hooks

@hooks.register('after_create_page')
def do_after_page_create(request, page):
    return HttpResponse("Congrats on making content!", content_type="text/plain")

Если вы задаёте атрибуты объекта Page, вы также должны вызвать save_revision(), так как представление «Редактировать» и представление «Индекс» берут свои данные из таблицы пересмотров, а не из фактического сохранённого записей страницы.

  @hooks.register('after_create_page')
  def set_attribute_after_page_create(request, page):
      page.title = 'Persistent Title'
      new_revision = page.save_revision()
      if page.live:
          # page has been created and published at the same time,
          # so ensure that the updated title is on the published version too
          new_revision.publish()

before_create_page

Вызывается в начале представления «создание страницы», передавая запрос, родительскую страницу и класс модели страницы.

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа и пропустит остальную часть представления.

В отличие от after_create_page, это выполняется как для запросов GET, так и для запросов POST.

Это можно использовать для полной замены редактора на уровне отдельного представления:

from wagtail import hooks

from .models import AwesomePage
from .admin_views import edit_awesome_page

@hooks.register('before_create_page')
def before_create_page(request, parent_page, page_class):
    # Use a custom create view for the AwesomePage model
    if page_class == AwesomePage:
        return create_awesome_page(request, parent_page)

after_delete_page

Выполните какие-либо действия после удаления объекта Page. Использует тот же механизм, что и after_create_page.

before_delete_page

Вызывается в начале представления «удаление страницы», передавая запрос и объект страницы.

Использует тот же механизм, что и before_create_page, выполняется как для запросов GET, так и для запросов POST.

from django.shortcuts import redirect
from django.utils.html import format_html

from wagtail.admin import messages
from wagtail import hooks

from .models import AwesomePage


@hooks.register('before_delete_page')
def before_delete_page(request, page):
    """Block awesome page deletion and show a message."""

    if request.method == 'POST' and page.specific_class in [AwesomePage]:
        messages.warning(request, "Awesome pages cannot be deleted, only unpublished")
        return redirect('wagtailadmin_pages:delete', page.pk)

after_edit_page

Выполните какие-либо действия с объектом Page после его обновления. Использует тот же механизм, что и after_create_page.

before_edit_page

Вызывается в начале представления «редактирование страницы», передавая запрос и объект страницы.

Использует тот же механизм, что и before_create_page.

after_publish_page

Выполните какие-либо действия с объектом Page после его публикации через представление «создание страницы» или представление «редактирование страницы».

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа и пропустит остальную часть представления.

before_publish_page

Выполните какие-либо действия с объектом Page перед его публикацией через представление «создание страницы» или представление «редактирование страницы».

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа и пропустит остальную часть представления.

after_unpublish_page

Вызывается после действия «снятия с публикации» в представлении «снятие с публикации», передавая запрос и объект страницы.

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа и пропустит остальную часть представления.

before_unpublish_page

Вызывается перед действием «снятие с публикации» в представлении «снятие с публикации», передавая запрос и объект страницы.

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа и пропустит остальную часть представления.

after_copy_page

Выполните какие-либо действия с объектом Page после его копирования, передавая запрос, объект страницы и новую скопированную страницу. Использует тот же механизм, что и after_create_page.

before_copy_page

Вызывается в начале представления «копирование страницы», передавая запрос и объект страницы.

Использует тот же механизм, что и before_create_page.

after_move_page

Выполните какие-либо действия с объектом Page после его перемещения, передавая запрос и объект страницы. Использует тот же механизм, что и after_create_page.

before_move_page

Вызывается в начале представления «перемещение страницы», передавая запрос, объект страницы и объект страницы назначения.

Использует тот же механизм, что и before_create_page.

before_convert_alias_page

Вызывается в начале представления convert_alias, которое отвечает за преобразование страниц-псевдонимов в обычные страницы Wagtail.

Запрос и преобразуемая страница передаются в качестве аргументов фишки.

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа и пропустит остальную часть представления.

after_convert_alias_page

Выполните какие-либо действия с объектом Page после его преобразования из псевдонима.

Запрос и страница, которая только что была преобразована, передаются в качестве аргументов фишки.

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его в качестве объекта ответа и пропустит остальную часть представления.

construct_translated_pages_to_cascade_actions

Возвращает дополнительные страницы для обработки в синхронизированной структуре дерева.

Эта фишка вызывается только при снятии страницы с публикации, когда WAGTAIL_I18N_ENABLED = True.

Список страниц и действие передаются в качестве аргументов фишки.

Функция должна вернуть словарь с страницей из списка страниц в качестве ключа и списком дополнительных страниц для выполнения действия. Мы рекомендуем, чтобы они были не псевдонимами, прямыми переводами страниц из аргумента функции.

register_page_action_menu_item

Добавляет элемент в всплывающее меню действий при создании и редактировании страниц. Вызываемая функция, переданная в эту фишку, должна вернуть экземпляр wagtail.admin.action_menu.ActionMenuItem. ActionMenuItem является подклассом компонента, поэтому отображение элемента меню можно настроить с помощью template_name, get_context_data, render_html и Media. Кроме того, доступны следующие атрибуты и методы для переопределения:

  • order - целое число (по умолчанию 100), которое определяет позицию элемента в меню. Также может быть передан в качестве ключевого аргумента конструктору объекта. Элемент с наименьшим номером в этом списке будет выбран по умолчанию; по умолчанию это «Сохранить черновик» (у которого order равен 0).
  • label - отображаемый текст элемента меню
  • get_url - метод, возвращающий URL для элемента меню; по умолчанию возвращает None, что заставляет элемент меню вести себя как кнопку отправки формы
  • name - значение атрибута name кнопки отправки, если URL не указан
  • icon_name - иконка для отображения рядом с элементом меню
  • classname - значение атрибута class для добавления к элементу кнопки
  • is_shown - метод, возвращающий логическое значение, показывающее, должен ли элемент меню отображаться; по умолчанию - true, за исключением редактирования заблокированной страницы

Методы get_url, is_shown, get_context_data и render_html все принимают словарь контекста, содержащий следующие поля:

  • view - имя текущего представления: 'create', 'edit' или 'revisions_revert'
  • page - для view = 'edit' или 'revisions_revert', редактируемая страница
  • parent_page - для view = 'create', родительская страница создаваемой страницы
  • request - текущий объект запроса
  • user_page_permissions - объект UserPagePermissionsProxy для текущего пользователя для проверки разрешений
from wagtail import hooks
from wagtail.admin.action_menu import ActionMenuItem

class GuacamoleMenuItem(ActionMenuItem):
    name = 'action-guacamole'
    label = "Guacamole"

    def get_url(self, context):
        return "https://www.youtube.com/watch?v=dNJdJIwCF_Y"


@hooks.register('register_page_action_menu_item')
def register_guacamole_menu_item():
    return GuacamoleMenuItem(order=10)

construct_page_action_menu

Изменяет окончательный список элементов меню действий при создании и редактировании страниц. Вызываемая функция, переданная в эту фишку, получает список объектов ActionMenuItem, объект запроса и словарь контекста, как в register_page_action_menu_item, и должна изменять список элементов меню на месте.

@hooks.register('construct_page_action_menu')
def remove_submit_to_moderator_option(menu_items, request, context):
    menu_items[:] = [item for item in menu_items if item.name != 'action-submit']

Фишка construct_page_action_menu вызывается после того, как элементы меню были отсортированы по атрибутам порядка, и поэтому установка порядка элемента меню не повлияет на этот момент. Вместо этого элементы можно переупорядочить, изменив их положение в списке, причём первый элемент будет выбран по умолчанию. Например, чтобы изменить действие по умолчанию на «Опубликовать»:

@hooks.register('construct_page_action_menu')
def make_publish_default_action(menu_items, request, context):
    for (index, item) in enumerate(menu_items):
        if item.name == 'action-publish':
            # move to top of list
            menu_items.pop(index)
            menu_items.insert(0, item)
            break

construct_page_listing_buttons

Изменяет окончательный список кнопок списка страниц в проводнике страниц. Вызываемая функция, переданная в эту фишку, получает список объектов PageListingButton, страницу, объект разрешений страницы и словарь контекста, как в register_page_listing_buttons, и должна изменять список элементов списка на месте.

@hooks.register('construct_page_listing_buttons')
def remove_page_listing_button_item(buttons, page, page_perms, context=None):
    if page.is_root:
        buttons.pop() # removes the last 'more' dropdown button on the root page listing buttons

construct_wagtail_userbar

Добавляет или удаляет элементы из панели инструментов wagtail. По умолчанию предоставляются инструменты добавления, редактирования и модерации. Вызываемая функция, переданная в фишку, должна принимать объект request и список объектов меню items. Объекты элементов меню должны иметь метод render, который может принять объект request и вернуть строку HTML, представляющую элемент меню. Для получения дополнительной информации обратитесь к шаблонам панели инструментов и классам элементов меню.

from wagtail import hooks

class UserbarPuppyLinkItem:
    def render(self, request):
        return '<li><a href="http://cuteoverload.com/tag/puppehs/" ' \
            + 'target="_parent" role="menuitem" class="action icon icon-wagtail">Puppies!</a></li>'

@hooks.register('construct_wagtail_userbar')
def add_puppy_link_item(request, items):
    return items.append( UserbarPuppyLinkItem() )

Рабочий процесс администратора

Обработчики для настройки способа, которым администраторы направляются по процессу редактирования пользователей.

after_create_user

Выполните какие-либо действия с объектом User после сохранения его в базе данных. Передаваемый в этот обработчик вызываемый объект должен принять объект request и объект user. Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его как объект ответа. По умолчанию Wagtail перенаправляет на страницу списка пользователей.

from django.http import HttpResponse

from wagtail import hooks

@hooks.register('after_create_user')
def do_after_create_user(request, user):
    return HttpResponse("Congrats on creating a new user!", content_type="text/plain")

before_create_user

Вызывается в начале представления «создание пользователя», передавая запрос.

Функция не обязана возвращать ничего, но если возвращается объект со свойством status_code, Wagtail будет использовать его как объект ответа и пропустит остальную часть представления.

В отличие от after_create_user, этот обработчик выполняется как для запросов GET, так и для запросов POST.

Это можно использовать для полного переопределения редактора пользователей на основе представления:

from django.http import HttpResponse

from wagtail import hooks

from .models import AwesomePage
from .admin_views import edit_awesome_page

@hooks.register('before_create_user')
def do_before_create_user(request):
    return HttpResponse("A user creation form", content_type="text/plain")

after_delete_user

Выполните какие-либо действия после удаления объекта User. Используется тот же метод, что и в after_create_user.

before_delete_user

Вызывается в начале представления «удаление пользователя», передавая запрос и объект пользователя.

Используется тот же метод, что и в before_create_user.

after_edit_user

Выполните какие-либо действия с объектом User после его обновления. Используется тот же метод, что и в after_create_user.

before_edit_user

Вызывается в начале представления «редактирование пользователя», передавая запрос и объект пользователя.

Используется тот же метод, что и в before_create_user.

Выбиратели

construct_page_chooser_queryset

Вызывается при отрисовке представления выбора страницы, чтобы разрешить настройку набора результатов запроса списка страниц. Вызываемый объект, переданный в обработчик, получит текущий набор результатов запроса страницы и объект запроса и должен вернуть набор результатов запроса Page (либо исходный, либо новый).

from wagtail import hooks

@hooks.register('construct_page_chooser_queryset')
def show_my_pages_only(pages, request):
    # Only show own pages
    pages = pages.filter(owner=request.user)

    return pages

construct_document_chooser_queryset

Вызывается при отрисовке представления выбора документа, чтобы разрешить настройку набора результатов запроса списка документов. Вызываемый объект, переданный в обработчик, получит текущий набор результатов запроса документов и объект запроса и должен вернуть набор результатов запроса Document (либо исходный, либо новый).

from wagtail import hooks

@hooks.register('construct_document_chooser_queryset')
def show_my_uploaded_documents_only(documents, request):
    # Only show uploaded documents
    documents = documents.filter(uploaded_by_user=request.user)

    return documents

construct_image_chooser_queryset

Вызывается при отрисовке представления выбора изображения, чтобы разрешить настройку набора результатов запроса списка изображений. Вызываемый объект, переданный в обработчик, получит текущий набор результатов запроса изображений и объект запроса и должен вернуть набор результатов запроса Image (либо исходный, либо новый).

from wagtail import hooks

@hooks.register('construct_image_chooser_queryset')
def show_my_uploaded_images_only(images, request):
    # Only show uploaded images
    images = images.filter(uploaded_by_user=request.user)

    return images

Обзор страниц

construct_explorer_page_queryset

Вызывается при отрисовке представления обзора страниц, чтобы разрешить настройку набора результатов запроса списка страниц. Вызываемый объект, переданный в обработчик, получит родительский объект страницы, текущий набор результатов запроса страницы и объект запроса и должен вернуть набор результатов запроса Page (либо исходный, либо новый).

from wagtail import hooks

@hooks.register('construct_explorer_page_queryset')
def show_my_profile_only(parent_page, pages, request):
    # If we're in the 'user-profiles' section, only show the user's own profile
    if parent_page.slug == 'user-profiles':
        pages = pages.filter(owner=request.user)

    return pages

register_page_listing_buttons

Добавление кнопок в список действий для страницы в обозревателе страниц. Это полезно при добавлении пользовательских действий в список, таких как перевод или сложный рабочий процесс.

Этот пример добавит простую кнопку в список:

from wagtail.admin import widgets as wagtailadmin_widgets

@hooks.register('register_page_listing_buttons')
def page_listing_buttons(page, page_perms, next_url=None):
    yield wagtailadmin_widgets.PageListingButton(
        'A page listing button',
        '/goes/to/a/url/',
        priority=10
    )

Аргументы, передаваемые в обработчик, следующие:

  • page — объект страницы, для которого генерируется кнопка
  • page_perms — объект, который можно запросить, чтобы определить разрешения текущего пользователя на данной странице
  • next_url — URL, на который связанное действие должно перенаправить после завершения действия, если представление его поддерживает

Аргумент priority управляет порядком отображения кнопок. Кнопки упорядочены от низкого к высокому приоритету, поэтому кнопка с priority=10 будет отображаться перед кнопкой с priority=20.

register_page_listing_more_buttons

Добавление кнопок в раскрывающееся меню «Ещё» для страницы в обозревателе страниц. Это работает аналогично обработчику register_page_listing_buttons, но полезно для менее используемых пользовательских действий, которые лучше подходят для раскрывающегося меню.

Этот пример добавит простую кнопку в раскрывающееся меню:

from wagtail.admin import widgets as wagtailadmin_widgets

@hooks.register('register_page_listing_more_buttons')
def page_listing_more_buttons(page, page_perms, next_url=None):
    yield wagtailadmin_widgets.Button(
        'A dropdown button',
        '/goes/to/a/url/',
        priority=60
    )

Аргументы, передаваемые в обработчик, следующие:

  • page — объект страницы, для которого генерируется кнопка
  • page_perms — объект, который можно запросить, чтобы определить разрешения текущего пользователя на данной странице
  • next_url — URL, на который связанное действие должно перенаправить после завершения действия, если представление его поддерживает

Аргумент priority управляет порядком отображения кнопок в раскрывающемся меню. Кнопки упорядочены от низкого к высокому приоритету, поэтому кнопка с priority=10 будет отображаться перед кнопкой с priority=60.

Кнопки со списками выпадающих меню

Модули администратора также предоставляют ButtonWithDropdownFromHook, что позволяет определить пользовательский обработчик для генерации выпадающего меню, которое прикрепляется к вашей кнопке.

Создание кнопки с выпадающим меню включает два шага. Во-первых, вы добавляете свою кнопку в обработчик register_page_listing_buttons, как показано в примере выше. Во-вторых, вы регистрируете новый обработчик, который выводит содержимое выпадающего меню.

В этом примере показано, как реализуется стандартное выпадающее меню администратора Wagtail. Вы также можете увидеть, как регистрировать кнопки условно, в этом случае путём оценки page_perms:

from wagtail.admin import widgets as wagtailadmin_widgets

@hooks.register('register_page_listing_buttons')
def page_custom_listing_buttons(page, page_perms, next_url=None):
    yield wagtailadmin_widgets.ButtonWithDropdownFromHook(
        'More actions',
        hook_name='my_button_dropdown_hook',
        page=page,
        page_perms=page_perms,
        next_url=next_url,
        priority=50
    )

@hooks.register('my_button_dropdown_hook')
def page_custom_listing_more_buttons(page, page_perms, next_url=None):
    if page_perms.can_move():
        yield wagtailadmin_widgets.Button('Move', reverse('wagtailadmin_pages:move', args=[page.id]), priority=10)
    if page_perms.can_delete():
        yield wagtailadmin_widgets.Button('Delete', reverse('wagtailadmin_pages:delete', args=[page.id]), priority=30)
    if page_perms.can_unpublish():
        yield wagtailadmin_widgets.Button('Unpublish', reverse('wagtailadmin_pages:unpublish', args=[page.id]), priority=40)

Шаблон для кнопки выпадающего меню можно настроить, переопределив wagtailadmin/pages/listing/_button_with_dropdown.html. JavaScript, который обрабатывает выпадающие меню, использует пользовательские атрибуты данных, поэтому вам следует оставить data-dropdown и data-dropdown-toggle в разметке, если вы её настраиваете.

Отображение страниц

before_serve_page

Вызывается, когда Wagtail собирается отобразить страницу. Вызываемый объект, переданный в обработчик, получит объект страницы, объект запроса и args и kwargs, которые будут переданы методу serve() страницы. Если вызываемый объект возвращает HttpResponse, этот ответ будет немедленно возвращён пользователю, и Wagtail не будет вызывать метод serve() на странице.

from django.http import HttpResponse

from wagtail import hooks

@hooks.register('before_serve_page')
def block_googlebot(page, request, serve_args, serve_kwargs):
    if request.META.get('HTTP_USER_AGENT') == 'GoogleBot':
        return HttpResponse("<h1>bad googlebot no cookie</h1>")

Отображение документов

before_serve_document

Вызывается, когда Wagtail собирается отобразить документ. Вызываемый объект, переданный в обработчик, получит объект документа и объект запроса. Если вызываемый объект возвращает HttpResponse, этот ответ будет немедленно возвращён пользователю вместо отображения документа. Обратите внимание, что этот обработчик будет пропущен, если параметр WAGTAILDOCS_SERVE_METHOD установлен в значение direct.

Сниппеты

Крючки для работы со зарегистрированными Сниппетами.

after_edit_snippet

Вызывается при редактировании Сниппета. Переданная в крючок функция получит экземпляр модели и объект запроса. Если функция вернёт HttpResponse, этот ответ будет немедленно возвращён пользователю, и Wagtail не будет вызывать redirect() к представлению списка.

from django.http import HttpResponse

from wagtail import hooks

@hooks.register('after_edit_snippet')
def after_snippet_update(request, instance):
    return HttpResponse(f"Congrats on editing a snippet with id {instance.pk}", content_type="text/plain")

before_edit_snippet

Вызывается в начале представления редактирования сниппета. Переданная в крючок функция получит экземпляр модели и объект запроса. Если функция вернёт HttpResponse, этот ответ будет немедленно возвращён пользователю, и Wagtail не будет вызывать redirect() к представлению списка.

from django.http import HttpResponse

from wagtail import hooks

@hooks.register('before_edit_snippet')
def block_snippet_edit(request, instance):
    if isinstance(instance, RestrictedSnippet) and instance.prevent_edit:
        return HttpResponse("Sorry, you can't edit this snippet", content_type="text/plain")

after_create_snippet

Вызывается при создании Сниппета. after_create_snippet и after_edit_snippet работают идентично. Единственное различие заключается в том, где вызывается крючок.

before_create_snippet

Вызывается в начале представления создания сниппета. Работает аналогично before_edit_snippet, за исключением того, что модель передаётся как аргумент вместо экземпляра.

after_delete_snippet

Вызывается при удалении Сниппета. Переданная в крючок функция получит экземпляр(ы) модели как набор запросов вместе с объектом запроса. Если функция вернёт HttpResponse, этот ответ будет немедленно возвращён пользователю, и Wagtail не будет вызывать redirect() к представлению списка.

from django.http import HttpResponse

from wagtail import hooks

@hooks.register('after_delete_snippet')
def after_snippet_delete(request, instances):
    # "instances" is a QuerySet
    total = len(instances)
    return HttpResponse(f"{total} snippets have been deleted", content_type="text/plain")

before_delete_snippet

Вызывается в начале представления удаления сниппета. Переданная в крючок функция получит экземпляр(ы) модели как набор запросов вместе с объектом запроса. Если функция вернёт HttpResponse, этот ответ будет немедленно возвращён пользователю, и Wagtail не будет вызывать redirect() к представлению списка.

from django.http import HttpResponse

from wagtail import hooks

@hooks.register('before_delete_snippet')
def before_snippet_delete(request, instances):
    # "instances" is a QuerySet
    total = len(instances)

    if request.method == 'POST':
      # Override the deletion behaviour
      instances.delete()

      return HttpResponse(f"{total} snippets have been deleted", content_type="text/plain")

register_snippet_action_menu_item

Добавляет элемент в всплывающее меню действий для создания и редактирования сниппетов. Переданная в этот крючок функция должна вернуть экземпляр wagtail.snippets.action_menu.ActionMenuItem. ActionMenuItem — подкласс Компонента, поэтому отображение пункта меню можно настроить с помощью template_name, get_context_data, render_html и Media. Кроме того, можно переопределить следующие атрибуты и методы:

  • order — целое число (по умолчанию 100), определяющее позицию элемента в меню. Также может быть передан в качестве ключевого аргумента конструктору объекта. Элемент с наименьшим номером в этой последовательности будет выбран по умолчанию; по умолчанию это «Сохранить черновик» (у которого order равен 0).
  • label — отображаемый текст пункта меню
  • get_url — метод, возвращающий URL для пункта меню; по умолчанию возвращает None, что заставляет пункт меню работать как кнопку отправки формы.
  • name — значение атрибута name кнопки отправки, если URL не указан
  • icon_name — иконка, отображаемая рядом с пунктом меню
  • classname — значение атрибута class для добавления к элементу кнопки
  • is_shown — метод, возвращающий логическое значение, указывающее, должен ли отображаться пункт меню; по умолчанию истинно, за исключением редактирования заблокированной страницы

Методы get_url, is_shown, get_context_data и render_html принимают словарь контекста, содержащий следующие поля:

  • view — имя текущего представления: 'create' или 'edit'
  • model — класс модели сниппета
  • instance — для view = 'edit', экземпляр, который редактируется
  • request — текущий объект запроса
from wagtail import hooks
from wagtail.snippets.action_menu import ActionMenuItem

class GuacamoleMenuItem(ActionMenuItem):
    name = 'action-guacamole'
    label = "Guacamole"

    def get_url(self, context):
        return "https://www.youtube.com/watch?v=dNJdJIwCF_Y"


@hooks.register('register_snippet_action_menu_item')
def register_guacamole_menu_item():
    return GuacamoleMenuItem(order=10)

construct_snippet_action_menu

Изменяет окончательный список пунктов меню действий в представлениях создания и редактирования сниппетов. Переданная в этот крючок функция получает список ActionMenuItem объектов, объект запроса и словарь контекста по аналогии с register_snippet_action_menu_item и должна изменить список пунктов меню на месте.

@hooks.register('construct_snippet_action_menu')
def remove_delete_option(menu_items, request, context):
    menu_items[:] = [item for item in menu_items if item.name != 'delete']

Крючок construct_snippet_action_menu вызывается после того, как пункты меню были отсортированы по их атрибутам порядка, поэтому установка порядка пункта меню не повлияет на этот момент. Вместо этого пункты можно переупорядочить, изменив их позицию в списке, при этом первый пункт будет выбран по умолчанию. Например, чтобы изменить действие по умолчанию на «Удалить»:

@hooks.register('construct_snippet_action_menu')
def make_delete_default_action(menu_items, request, context):
    for (index, item) in enumerate(menu_items):
        if item.name == 'delete':
            # move to top of list
            menu_items.pop(index)
            menu_items.insert(0, item)
            break

register_snippet_listing_buttons

Добавляет кнопки в список действий для сниппета в списке сниппетов. Это полезно при добавлении пользовательских действий в список, таких как перевод или сложный рабочий процесс.

Этот пример добавит простую кнопку в список:

from wagtail.snippets import widgets as wagtailsnippets_widgets

@hooks.register('register_snippet_listing_buttons')
def snippet_listing_buttons(snippet, user, next_url=None):
    yield wagtailsnippets_widgets.SnippetListingButton(
        'A page listing button',
        '/goes/to/a/url/',
        priority=10
    )

Аргументы, передаваемые в крючок, следующие:

  • snippet — объект сниппета для генерации кнопки
  • user — пользователь, просматривающий список сниппетов
  • next_url — URL, на который должна перенаправить связанное действие по завершении действия, если представление его поддерживает

Аргумент priority управляет порядком отображения кнопок. Кнопки упорядочены от низкого к высокому приоритету, поэтому кнопка с priority=10 будет отображаться до кнопки с priority=20.

construct_snippet_listing_buttons

Изменяет окончательный список кнопок списка сниппетов. Переданная в этот крючок функция получает список SnippetListingButton объектов, пользователя и словарь контекста по аналогии с register_snippet_listing_buttons и должна изменить список пунктов меню на месте.

@hooks.register('construct_snippet_listing_buttons')
def remove_snippet_listing_button_item(buttons, snippet, user, context=None):
    buttons.pop()  # Removes the 'delete' button

Массовые действия

Крючки для регистрации и настройки массовых действий. Смотрите Добавление пользовательских массовых действий, как написать пользовательские массовые действия.

register_bulk_action

Регистрирует новое массовое действие для добавления в список массовых действий в проводнике.

Этот крючок должен быть зарегистрирован с подклассом BulkAction. Например:

from wagtail.admin.views.bulk_action import BulkAction
from wagtail import hooks


@hooks.register("register_bulk_action")
class CustomBulkAction(BulkAction):
    display_name = _("Custom Action")
    action_type = "action"
    aria_label = _("Do custom action")
    template_name = "/path/to/template"
    models = [...]  # list of models the action should execute upon


    @classmethod
    def execute_action(cls, objects, **kwargs):
        for object in objects:
            do_something(object)
        return num_parent_objects, num_child_objects  # return the count of updated objects

before_bulk_action

Выполняет действия непосредственно перед выполнением массового действия (перед вызовом метода execute_action).

Этот крючок может быть использован для возврата ответа HTTP. Например:

from wagtail import hooks

@hooks.register("before_bulk_action")
def hook_func(request, action_type, objects, action_class_instance):
  if action_type == 'delete':
    return HttpResponse(f"{len(objects)} objects would be deleted", content_type="text/plain")

after_bulk_action

Выполняет действия непосредственно после выполнения массового действия (после вызова метода execute_action).

Этот крючок может быть использован для возврата ответа HTTP. Например:

from wagtail import hooks

@hooks.register("after_bulk_action")
def hook_func(request, action_type, objects, action_class_instance):
  if action_type == 'delete':
    return HttpResponse(f"{len(objects)} objects have been deleted", content_type="text/plain")

Журнал аудита

register_log_actions

См. Журнал аудита

Чтобы добавить новые действия в реестр, вызовите метод register_action с типом действия, его меткой и сообщением, которое будет отображаться в административных списках.

from django.utils.translation import gettext_lazy as _

from wagtail import hooks

@hooks.register('register_log_actions')
def additional_log_actions(actions):
    actions.register_action('wagtail_package.echo', _('Echo'), _('Sent an echo'))

В качестве альтернативы, для сообщения журнала, которое варьируется в зависимости от данных записи журнала, создайте подкласс wagtail.log_actions.LogFormatter, который переопределяет метод format_message, и используйте register_action как декоратор на этом классе:

from django.utils.translation import gettext_lazy as _

from wagtail import hooks
from wagtail.log_actions import LogFormatter

@hooks.register('register_log_actions')
def additional_log_actions(actions):
    @actions.register_action('wagtail_package.greet_audience')
    class GreetingActionFormatter(LogFormatter):
        label = _('Greet audience')

        def format_message(self, log_entry):
            return _('Hello %(audience)s') % {
                'audience': log_entry.data['audience'],
            }

Изменено в версии 2.15: Класс LogFormatter был представлен. Ранее динамические сообщения достигались путём передачи вызываемой функции в качестве аргумента message к register_action.

© 2014-present Torchbox Ltd and individual contributors.
All rights are reserved.
Licensed under the BSD License.
https://docs.wagtail.org/en/stable/reference/hooks.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API