Spec-Zone.ru › Wagtail 2

Гаксы

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

Примечание

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

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

from wagtail.core 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

Тестирование гаков в отдельных блоках

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

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

def my_hook_function():
    ...

class MyHookTest(TestCase):

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

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

def my_hook_function():
    ...

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.core 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, поскольку элементы, добавленные через construct_main_menu, не будут проверены на is_shown.

from wagtail.core 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 (чтобы указать отсутствие объектов в этой коллекции), либо словарь, содержащий следующие ключи:

register_account_settings_panel

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

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

from wagtail.admin.views.account import BaseSettingsPanel
from wagtail.core 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.core 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.core 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: внутреннее имя, используемое для идентификации пункта меню; по умолчанию соответствует slug-форме метки.
icon_name: иконка, отображаемая рядом с пунктом меню; нет значений по умолчанию, необязательно, но должна быть установлена для пунктов меню верхнего уровня, чтобы их можно было идентифицировать при сворачивании.
classnames: дополнительные CSS-классы, применяемые к ссылке
order: целое число, определяющее позицию элемента в меню

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

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

from django.urls import reverse

from wagtail.core 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-адресов страниц администрирования. Передаваемая в этот гак вызываемая функция должна вернуть список шаблонов URL Django, определяющих структуру страниц и конечных точек вашего расширения для администрирования Wagtail. Для получения дополнительной информации о стандартных Django URLconf и представлениях см. диспетчер URL.

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

from wagtail.core 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_admin_search_area

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

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

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

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

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

from django.urls import reverse
from wagtail.core 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

Возвращает набор объектов Permission для отображения в области администрирования групп.

from django.contrib.auth.models import Permission
from wagtail.core 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, содержащий подмножество страниц форм, к которым пользователь имеет разрешение доступа к отправленным формам.

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

from wagtail.core 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.core 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.core 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.core 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.html import format_html

from wagtail.core import hooks

@hooks.register('insert_global_admin_js')
def global_admin_js():
    return format_html(
        '<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.core 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.core 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.core 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 будет использовать его как объект ответа и пропустит остальную часть представления.

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.core 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, is_parent=False, context=None):
    if is_parent:
        buttons.pop() # removes the last 'more' dropdown button on the parent page listing buttons

construct_wagtail_userbar

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

from wagtail.core 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.core import hooks

@hooks.register('after_create_user')
def do_after_page_create(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.core import hooks

from .models import AwesomePage
from .admin_views import edit_awesome_page

@hooks.register('before_create_user')
def before_create_page(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

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

from wagtail.core 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

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

from wagtail.core 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

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

from wagtail.core 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

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

from wagtail.core 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, is_parent=False, next_url=None):
    yield wagtailadmin_widgets.PageListingButton(
        'A page listing button',
        '/goes/to/a/url/',
        priority=10
    )

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

  • page - объект страницы для генерации кнопки
  • page_perms - объект PagePermissionTester, который можно запросить, чтобы определить права текущего пользователя на данной странице
  • is_parent - если true, эта кнопка отображается для родительской страницы, отображаемой в верхней части списка
  • 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, is_parent=False, next_url=None):
    yield wagtailadmin_widgets.Button(
        'A dropdown button',
        '/goes/to/a/url/',
        priority=60
    )

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

  • page - объект страницы для генерации кнопки
  • page_perms - объект PagePermissionTester, который можно запросить, чтобы определить права текущего пользователя на данной странице
  • is_parent - если true, эта кнопка отображается для родительской страницы, отображаемой в верхней части списка
  • 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, is_parent=False, next_url=None):
    yield wagtailadmin_widgets.ButtonWithDropdownFromHook(
        'More actions',
        hook_name='my_button_dropdown_hook',
        page=page,
        page_perms=page_perms,
        is_parent=is_parent,
        next_url=next_url,
        priority=50
    )

@hooks.register('my_button_dropdown_hook')
def page_custom_listing_more_buttons(page, page_perms, is_parent=False, 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.core 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.core 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.core 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.core 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.core 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: метод, возвращающий булево значение, указывающее, должен ли отображаться элемент меню; по умолчанию true, за исключением редактирования заблокированной страницы

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

view: имя текущего просмотра: 'create' или 'edit'
model: Класс модели фрагмента
instance: При view = 'edit', экземпляр, который редактируется
request: Текущий объект запроса
from wagtail.core 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 вызывается после сортировки элементов меню по их атрибутам order, и поэтому установка порядка элемента меню в этот момент не повлияет. Вместо этого элементы можно переупорядочить, изменив их позицию в списке, при этом первый элемент будет выбран по умолчанию. Например, чтобы изменить действие по умолчанию на Удалить:

@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.core 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.core 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.core 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.core import hooks

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

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

from django.utils.translation import gettext_lazy as _

from wagtail.core import hooks
from wagtail.core.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.

  • Предыдущее Команды управления
  • Следующее Сигналы

Содержание страницы

  • Обработчики
    • Обработчики тестирования юнит-тестов
    • Модули администрирования
      • construct_homepage_panels
      • construct_homepage_summary_items
      • construct_main_menu
      • describe_collection_contents
      • register_account_settings_panel
      • register_account_menu_item
      • register_admin_menu_item
      • register_admin_urls
      • register_group_permission_panel
      • register_settings_menu_item
      • construct_settings_menu
      • register_reports_menu_item
      • construct_reports_menu
      • register_admin_search_area
      • register_permissions
      • filter_form_submissions_for_user
    • Интерфейс редактора
      • register_rich_text_features
      • insert_editor_css
      • insert_global_admin_css
      • insert_editor_js
      • insert_global_admin_js
      • register_page_header_buttons
    • Рабочий процесс редактора
      • after_create_page
      • before_create_page
      • after_delete_page
      • before_delete_page
      • after_edit_page
      • before_edit_page
      • after_publish_page
      • before_publish_page
      • after_unpublish_page
      • before_unpublish_page
      • after_copy_page
      • before_copy_page
      • after_move_page
      • before_move_page
      • before_convert_alias_page
      • after_convert_alias_page
      • register_page_action_menu_item
      • construct_page_action_menu
      • construct_page_listing_buttons
      • construct_wagtail_userbar
    • Рабочий процесс администратора
      • after_create_user
      • before_create_user
      • after_delete_user
      • before_delete_user
      • after_edit_user
      • before_edit_user
    • Выборщики
      • construct_page_chooser_queryset
      • construct_document_chooser_queryset
      • construct_image_chooser_queryset
    • Проводник страниц
      • construct_explorer_page_queryset
      • register_page_listing_buttons
      • register_page_listing_more_buttons
        • Кнопки со списками выпадающего меню
    • Отображение страниц
      • before_serve_page
    • Отображение документов
      • before_serve_document
    • Сниппеты
      • after_edit_snippet
      • before_edit_snippet
      • after_create_snippet
      • before_create_snippet
      • after_delete_snippet
      • before_delete_snippet
      • register_snippet_action_menu_item
      • construct_snippet_action_menu
      • register_snippet_listing_buttons
      • construct_snippet_listing_buttons
    • Массовые действия
      • register_bulk_action
      • before_bulk_action
      • after_bulk_action
    • Журнал аудита
      • register_log_actions

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

Spec-Zone.ru

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