Компоненты шаблонов
Работа с объектами, которые знают, как отображать себя как элементы в HTML-шаблоне, — это распространённый шаблон, встречающийся в админ-панели Wagtail. Например, главная страница админ-панели — это представление, предоставляемое центральным приложением wagtail.admin, но объединяющее панели с информацией, полученные из различных других модулей Wagtail, таких как изображения и документы (возможно, вместе с другими, предоставленными сторонними пакетами). Эти панели передаются на главную страницу через хук construct_homepage_panels, и каждый из них отвечает за предоставление собственного HTML-отображения. Таким образом, модуль, предоставляющий панель, полностью контролирует её внешний вид на главной странице.
Wagtail реализует этот шаблон с использованием стандартного типа объекта, известного как компонент. Компонент — это объект Python, предоставляющий следующие методы и свойства:
Принимая на вход словарь контекста из вызывающего шаблона (который может быть объектом Context или простым dict из переменных контекста), возвращает строковое представление, которое будет вставлено в шаблон. Это будет подчиняться правилам экранирования HTML Django, поэтому возвращаемое значение, состоящее из HTML, обычно должно возвращаться как экземпляр SafeString.
Возможный (пустой) объект form media, определяющий JavaScript- и CSS-ресурсы, используемые компонентом.
Примечание
Любой объект, реализующий этот API, может считаться допустимым компонентом; он не обязательно должен наследоваться от класса Component, описанного ниже, и пользовательский код, работающий с компонентами, не должен этого предполагать (например, он не должен использовать isinstance для проверки, является ли данное значение компонентом).
Создание компонентов
Предпочтительный способ создания компонента — определить подкласс wagtail.admin.ui.components.Component и указать атрибут template_name на нём. Затем отрендеренный шаблон будет использоваться как HTML-представление компонента:
from wagtail.admin.ui.components import Component
class WelcomePanel(Component):
template_name = 'my_app/panels/welcome.html'
my_welcome_panel = WelcomePanel()
my_app/templates/my_app/panels/welcome.html:
<h1>Welcome to my app!</h1>
В простых случаях, не требующих шаблона, вместо этого можно переопределить метод render_html:
from django.utils.html import format_html
from wagtail.admin.components import Component
class WelcomePanel(Component):
def render_html(self, parent_context):
return format_html("<h1>{}</h1>", "Welcome to my app!")
Передача контекста в шаблон
Метод get_context_data можно переопределить, чтобы передать переменные контекста в шаблон. Как и в случае с render_html, он получает словарь контекста из вызывающего шаблона:
from wagtail.admin.ui.components import Component
class WelcomePanel(Component):
template_name = 'my_app/panels/welcome.html'
def get_context_data(self, parent_context):
context = super().get_context_data(parent_context)
context['username'] = parent_context['request'].user.username
return context
my_app/templates/my_app/panels/welcome.html:
<h1>Welcome to my app, {{ username }}!</h1>
Добавление определений медиа
Как и виджеты Django-форм, компоненты могут указывать связанные JavaScript- и CSS-ресурсы, используя внутренний класс Media или динамическое свойство media:
class WelcomePanel(Component):
template_name = 'my_app/panels/welcome.html'
class Media:
css = {
'all': ('my_app/css/welcome-panel.css',)
}
Использование компонентов в собственных шаблонах
Библиотека тегов wagtailadmin_tags предоставляет тег {% component %} для включения компонентов в шаблон. Это позаботится о передаче переменных контекста из вызывающего шаблона в компонент (чего не произойдёт в случае с базовым тегом переменной {{ ... }}). Например, при таком представлении:
from django.shortcuts import render
def welcome_page(request):
panels = [
WelcomePanel(),
]
render(request, 'my_app/welcome.html', {
'panels': panels,
})
шаблон my_app/welcome.html мог бы отображать панели следующим образом:
{% load wagtailadmin_tags %}
{% for panel in panels %}
{% component panel %}
{% endfor %}
Обратите внимание, что выводом любых объявлений медиа, определённых в компонентах, занимается ваш шаблон. В представлении Wagtail админ-панели это лучше всего сделать, создав объект media для всей страницы внутри представления, передав его в шаблон и выведя его через блоки extra_js и extra_css базового шаблона:
from django.forms import Media
from django.shortcuts import render
def welcome_page(request):
panels = [
WelcomePanel(),
]
media = Media()
for panel in panels:
media += panel.media
render(request, 'my_app/welcome.html', {
'panels': panels,
'media': media,
})
my_app/welcome.html:
{% extends "wagtailadmin/base.html" %}
{% load wagtailadmin_tags %}
{% block extra_js %}
{{ block.super }}
{{ media.js }}
{% endblock %}
{% block extra_css %}
{{ block.super }}
{{ media.css }}
{% endblock %}
{% block content %}
{% for panel in panels %}
{% component panel %}
{% endfor %}
{% endblock %}
© 2014-present Torchbox Ltd and individual contributors.
All rights are reserved.
Licensed under the BSD License.
https://docs.wagtail.org/en/v2.16.3/extending/template_components.html