Гаксы
При загрузке 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
Тестирование гаков в среде разработки
Гаксы обычно регистрируются при запуске и не могут быть изменены во время выполнения. Но при написании юнит-тестов вы можете захотеть зарегистрировать функцию-гак только для одного теста или блока кода и отменить её регистрацию, чтобы она не выполнялась при запуске других тестов.
Вы можете временно зарегистрировать гаки, используя функцию 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 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 с добавлением следующих дополнительных методов и свойств:
describe_collection_contents
Вызывается, когда Wagtail нужно узнать, какие объекты существуют в коллекции, если таковые есть. В настоящее время это происходит при подтверждении перед удалением коллекции, чтобы убедиться, что пустые коллекции не могут быть удалены. Передаваемая в этот гак функция получит объект collection и должна вернуть либо None (чтобы указать отсутствие объектов в этой коллекции), либо словарь, содержащий следующие ключи:
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_admin_urls
Регистрация дополнительных URL-адресов страниц админ-панели. Передаваемая в этот гак функция должна вернуть список шаблонов URL Django, которые определяют структуру страниц и точек входа вашего расширения для админ-панели Wagtail. Подробнее о стандартных Django URLconfs и представлениях см. диспетчер 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_admin_search_area
Добавление элемента в поиск Wagtail-админ-панели «Другие поиски». Поведение этого гака аналогично register_admin_menu_item. Передаваемая в этот гак функция должна вернуть экземпляр wagtail.admin.search.SearchArea. Новые элементы можно создать из класса SearchArea, передав следующие параметры:
Установка 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, содержащий подмножество этих страниц форм, к которым пользователь имеет разрешение для доступа.
Например, чтобы предотвратить доступ к отправкам форм для не-суперпользователей:
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>',
)
Рабочий процесс редактора
Крючки для настройки способа, которым пользователи проходят процесс создания контента страницы.
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_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_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 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
Вызывается при отображении представления выбора страницы, чтобы позволить настроить запрос QuerySet для списка страниц. Передаваемая в обработчик функция получит текущий запрос QuerySet страницы и объект запроса, и должна вернуть запрос QuerySet страницы (либо исходный, либо новый).
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
Вызывается при отображении представления выбора документа, чтобы позволить настроить запрос QuerySet для списка документов. Передаваемая в обработчик функция получит текущий запрос QuerySet документа и объект запроса, и должна вернуть запрос QuerySet документа (либо исходный, либо новый).
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
Вызывается при отображении представления выбора изображения, чтобы позволить настроить запрос QuerySet для списка изображений. Передаваемая в обработчик функция получит текущий запрос QuerySet изображения и объект запроса, и должна вернуть запрос QuerySet изображения (либо исходный, либо новый).
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
Вызывается при отображении представления обзора страниц, чтобы позволить настроить запрос QuerySet для списка страниц. Передаваемая в обработчик функция получит родительский объект страницы, текущий запрос QuerySet страницы и объект запроса, и должна вернуть запрос QuerySet страницы (либо исходный, либо новый).
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
Обслуживание страницы
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
Вызывается при удалении Сниппета. Переданная в хук функция получит набор экземпляров модели (как объект QuerySet) и объект запроса. Если функция вернёт 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
Вызывается в начале просмотра страницы удаления сниппета. Переданная в хук функция получит набор экземпляров модели (как объект QuerySet) и объект запроса. Если функция вернёт 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_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/v3.0.3/reference/hooks.html