(template_components)=
# 템플릿 컴포넌트
HTML 템플릿에 엘리먼트로 렌더링하는 방법을 아는 객체로 작업하는 것은 Wagtail 관리자 전체에서 볼 수 있는 일반적인 패턴입니다. 예를 들어, 관리자 홈페이지는 중앙 `wagtail.admin` 앱에서 제공하는 뷰이지만, 이미지 및 문서와 같은 Wagtail의 다양한 다른 모듈(타사 패키지에서 제공하는 다른 모듈과 함께)에서 가져온 정보 패널을 함께 제공합니다. 이러한 패널은 [`construct_homepage_panels`](construct_homepage_panels) 후크를 통해 홈페이지에 전달되며, 각 패널은 자체 HTML 렌더링을 제공할 책임이 있습니다. 이러한 방식으로 패널을 제공하는 모듈은 홈페이지에 표시되는 방식에 대한 완전한 제어권을 갖습니다.
Wagtail은 **컴포넌트**라는 표준 객체 유형을 사용하여 이 패턴을 구현합니다. 컴포넌트는 다음 메서드와 속성을 제공하는 Python 객체입니다.
```{eval-rst}
.. method:: render_html(self, parent_context=None)
호출 템플릿의 컨텍스트 사전( :py:class:`Context ` 객체 또는 컨텍스트 변수의 일반 :code:`dict` 일 수 있음)이 주어지면 템플릿에 삽입할 문자열 표현을 반환합니다. 이는 Django의 HTML 이스케이프 규칙의 적용을 받으므로 HTML로 구성된 반환 값은 일반적으로 :py:mod:`SafeString ` 인스턴스로 반환되어야 합니다.
.. attribute:: media
컴포넌트에서 사용하는 JavaScript 및 CSS 리소스를 정의하는 (비어 있을 수 있는) :doc:` 폼 미디어 ` 객체입니다.
```
```{note}
이 API를 구현하는 모든 객체는 유효한 컴포넌트로 간주될 수 있습니다. 아래에 설명된 `Component` 클래스에서 반드시 상속할 필요는 없으며, 컴포넌트로 작업하는 사용자 코드는 이를 가정해서는 안 됩니다(예를 들어, 주어진 값이 컴포넌트인지 확인하기 위해 `isinstance` 를 사용해서는 안 됩니다).
```
```{note}
버전 6.0부터 Wagtail은 [Laces](https://pypi.org/project/laces/) 라이브러리를 사용하여 모든 컴포넌트 관련 구현을 제공합니다.
Laces 라이브러리는 "템플릿 컴포넌트" 개념을 더 넓은 Django 생태계에서 사용할 수 있도록 Wagtail에서 추출되었습니다.
아래에 표시된 모든 가져오기 경로는 계속 작동하지만 Laces의 구현에 대한 참조일 뿐입니다.
"템플릿 컴포넌트"는 Wagtail 관리자 확장에만 국한되지 않습니다. 아래의 개념과 도구를 사용자 대면 코드에서도 사용할 수 있습니다.
컴포넌트 사용에 대한 자세한 정보는 [Laces 문서](https://github.com/tbrlpld/laces/blob/main/README.md)에서 찾을 수 있습니다.
```
(creating_template_components)=
## 컴포넌트 생성하기
컴포넌트를 만드는 가장 좋은 방법은 `wagtail.admin.ui.components.Component` 의 서브클래스를 정의하고 `template_name` 속성을 지정하는 것입니다. 그러면 렌더링된 템플릿이 컴포넌트의 HTML 표현으로 사용됩니다.
```python
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`:
```html+django
내 앱에 오신 것을 환영합니다!
```
템플릿이 필요 없는 간단한 경우에는 `render_html` 메서드를 대신 재정의할 수 있습니다.
```python
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("{}
", "내 앱에 오신 것을 환영합니다!")
```
## 템플릿에 컨텍스트 전달하기
`get_context_data` 메서드를 재정의하여 컨텍스트 변수를 템플릿에 전달할 수 있습니다. `render_html` 과 마찬가지로 이 메서드는 호출 템플릿에서 컨텍스트 사전을 받습니다.
```python
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`:
```html+django
{{ username }}님, 내 앱에 오신 것을 환영합니다!
```
## 미디어 정의 추가하기
Django 폼 위젯과 마찬가지로 컴포넌트는 내부 `Media` 클래스 또는 동적 `media` 속성을 사용하여 관련 JavaScript 및 CSS 리소스를 지정할 수 있습니다.
```python
class WelcomePanel(Component):
template_name = 'my_app/panels/welcome.html'
class Media:
css = {
'all': ('my_app/css/welcome-panel.css',)
}
```
## 자신의 템플릿에서 컴포넌트 사용하기
`wagtailadmin_tags` 태그 라이브러리는 템플릿에 컴포넌트를 포함하기 위한 `{% component %}` 태그를 제공합니다. 이 태그는 호출 템플릿의 컨텍스트 변수를 컴포넌트로 전달하는 작업을 처리합니다(기본 `{{ ... }}` 변수 태그의 경우는 그렇지 않음). 예를 들어, 다음 뷰가 주어졌을 때:
```python
from django.shortcuts import render
def welcome_page(request):
panels = [
WelcomePanel(),
]
render(request, 'my_app/welcome.html', {
'panels': panels,
})
```
`my_app/welcome.html` 템플릿은 다음과 같이 패널을 렌더링할 수 있습니다.
```html+django
{% load wagtailadmin_tags %}
{% for panel in panels %}
{% component panel %}
{% endfor %}
```
`with` 키워드를 사용하여 컴포넌트에 추가 컨텍스트 변수를 전달할 수 있습니다.
```html+django
{% component panel with username=request.user.username %}
```
제공된 변수만으로 (그리고 호출 템플릿의 컨텍스트에서 다른 변수 없이) 컴포넌트를 렌더링하려면 `only` 를 사용하십시오.
```html+django
{% component panel with username=request.user.username only %}
```
컴포넌트의 렌더링된 출력을 즉시 출력하는 대신 변수에 저장하려면 `as` 다음에 변수 이름을 사용하십시오.
```html+django
{% component panel as panel_html %}
{{ panel_html }}
```
컴포넌트에 정의된 모든 미디어 선언을 출력하는 것은 템플릿의 책임입니다. Wagtail 관리자 뷰의 경우, 뷰 내에서 전체 페이지에 대한 미디어 객체를 구성하고 이를 템플릿에 전달한 다음 기본 템플릿의 `extra_js` 및 `extra_css` 블록을 통해 출력하는 것이 가장 좋습니다.
```python
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`:
```html+django
{% 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 %}
```