템플릿 컴포넌트

HTML 템플릿에 엘리먼트로 렌더링하는 방법을 아는 객체로 작업하는 것은 Wagtail 관리자 전체에서 볼 수 있는 일반적인 패턴입니다. 예를 들어, 관리자 홈페이지는 중앙 wagtail.admin 앱에서 제공하는 뷰이지만, 이미지 및 문서와 같은 Wagtail의 다양한 다른 모듈(타사 패키지에서 제공하는 다른 모듈과 함께)에서 가져온 정보 패널을 함께 제공합니다. 이러한 패널은 construct_homepage_panels 후크를 통해 홈페이지에 전달되며, 각 패널은 자체 HTML 렌더링을 제공할 책임이 있습니다. 이러한 방식으로 패널을 제공하는 모듈은 홈페이지에 표시되는 방식에 대한 완전한 제어권을 갖습니다.

Wagtail은 컴포넌트라는 표준 객체 유형을 사용하여 이 패턴을 구현합니다. 컴포넌트는 다음 메서드와 속성을 제공하는 Python 객체입니다.

render_html(self, parent_context=None)

호출 템플릿의 컨텍스트 사전( Context 객체 또는 컨텍스트 변수의 일반 dict 일 수 있음)이 주어지면 템플릿에 삽입할 문자열 표현을 반환합니다. 이는 Django의 HTML 이스케이프 규칙의 적용을 받으므로 HTML로 구성된 반환 값은 일반적으로 SafeString 인스턴스로 반환되어야 합니다.

media

컴포넌트에서 사용하는 JavaScript 및 CSS 리소스를 정의하는 (비어 있을 수 있는) :doc:` 폼 미디어 <django:topics/forms/media>` 객체입니다.

참고

이 API를 구현하는 모든 객체는 유효한 컴포넌트로 간주될 수 있습니다. 아래에 설명된 Component 클래스에서 반드시 상속할 필요는 없으며, 컴포넌트로 작업하는 사용자 코드는 이를 가정해서는 안 됩니다(예를 들어, 주어진 값이 컴포넌트인지 확인하기 위해 isinstance 를 사용해서는 안 됩니다).

참고

버전 6.0부터 Wagtail은 Laces 라이브러리를 사용하여 모든 컴포넌트 관련 구현을 제공합니다.

Laces 라이브러리는 “템플릿 컴포넌트” 개념을 더 넓은 Django 생태계에서 사용할 수 있도록 Wagtail에서 추출되었습니다.

아래에 표시된 모든 가져오기 경로는 계속 작동하지만 Laces의 구현에 대한 참조일 뿐입니다.

“템플릿 컴포넌트”는 Wagtail 관리자 확장에만 국한되지 않습니다. 아래의 개념과 도구를 사용자 대면 코드에서도 사용할 수 있습니다.

컴포넌트 사용에 대한 자세한 정보는 Laces 문서에서 찾을 수 있습니다.

컴포넌트 생성하기

컴포넌트를 만드는 가장 좋은 방법은 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>내 앱에 오신 것을 환영합니다!</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>", "내 앱에 오신 것을 환영합니다!")

템플릿에 컨텍스트 전달하기

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>{{ username }}님, 내 앱에 오신 것을 환영합니다!</h1>

미디어 정의 추가하기

Django 폼 위젯과 마찬가지로 컴포넌트는 내부 Media 클래스 또는 동적 media 속성을 사용하여 관련 JavaScript 및 CSS 리소스를 지정할 수 있습니다.

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 %}

with 키워드를 사용하여 컴포넌트에 추가 컨텍스트 변수를 전달할 수 있습니다.

{% component panel with username=request.user.username %}

제공된 변수만으로 (그리고 호출 템플릿의 컨텍스트에서 다른 변수 없이) 컴포넌트를 렌더링하려면 only 를 사용하십시오.

{% component panel with username=request.user.username only %}

컴포넌트의 렌더링된 출력을 즉시 출력하는 대신 변수에 저장하려면 as 다음에 변수 이름을 사용하십시오.

{% component panel as panel_html %}

{{ panel_html }}

컴포넌트에 정의된 모든 미디어 선언을 출력하는 것은 템플릿의 책임입니다. Wagtail 관리자 뷰의 경우, 뷰 내에서 전체 페이지에 대한 미디어 객체를 구성하고 이를 템플릿에 전달한 다음 기본 템플릿의 extra_jsextra_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 %}