관리자 뷰 생성하기¶
Wagtail 관리자에 사용자 정의 뷰를 추가하는 가장 일반적인 용도는 Django 모델 관리를 위한 인터페이스를 제공하는 것입니다. Wagtail은 스니펫를 사용하여 최소한의 설정으로 Django 모델을 나열, 생성 및 편집할 수 있는 기성 뷰를 제공합니다.
이 패턴에 맞지 않는 다른 종류의 관리자 뷰의 경우, 직접 Django 뷰를 작성하고 훅(hooks)을 통해 Wagtail 관리자의 일부로 등록할 수 있습니다. 이 예제에서는 Python 표준 라이브러리의 calendar 모듈을 사용하여 현재 연도의 달력을 표시하는 뷰를 구현해 보겠습니다.
뷰 정의하기¶
Wagtail 프로젝트 내에서 ./manage.py startapp wagtailcalendar 명령으로 새로운 wagtailcalendar 앱을 생성하고 프로젝트의 INSTALLED_APPS 에 추가합니다. (이 경우, 표준 라이브러리의 calendar 모듈과의 충돌을 피하기 위해 ‘wagtailcalendar’라는 이름을 사용합니다. 일반적으로 ‘wagtail’ 접두사를 사용할 필요는 없습니다.)
views.py 를 다음과 같이 편집합니다. 이것은 Wagtail 관련 코드가 없는 순수 Django 뷰입니다.
import calendar
from django.http import HttpResponse
from django.utils import timezone
def index(request):
current_year = timezone.now().year
calendar_html = calendar.HTMLCalendar().formatyear(current_year)
return HttpResponse(calendar_html)
URL 라우트 등록하기¶
이 시점에서 Django 프로젝트의 표준적인 방법은 프로젝트의 최상위 URL 설정 모듈에 이 뷰에 대한 URL 라우트를 추가하는 것입니다. 하지만 이 경우에는 뷰가 로그인한 사용자에게만 제공되고, Wagtail이 관리하는 /admin/ URL 네임스페이스 내에 나타나기를 원합니다. 이는 Register Admin URLs 훅을 통해 수행됩니다.
시작 시 Wagtail은 각 설치된 앱 내에서 wagtail_hooks 서브 모듈을 찾습니다. 이 서브 모듈에서는 관리자용 URL 설정을 빌드하고 주 메뉴를 구성하는 등 Wagtail 작동의 다양한 시점에서 실행될 함수를 정의할 수 있습니다.
wagtailcalendar 앱 내에 wagtail_hooks.py 파일을 만들고 다음 내용을 포함합니다.
from django.urls import path
from wagtail import hooks
from .views import index
@hooks.register('register_admin_urls')
def register_calendar_url():
return [
path('calendar/', index, name='calendar'),
]
이제 달력은 /admin/calendar/ URL에서 볼 수 있습니다.

템플릿 추가하기¶
현재 이 뷰는 순수한 HTML 조각을 출력하고 있습니다. Wagtail의 기본 템플릿인 "wagtailadmin/base.html" 을 확장하는 템플릿을 만들어 이를 일반적인 Wagtail 관리자 페이지 구조에 삽입해 보겠습니다.
참고
기본 템플릿과 HTML 구조는 Wagtail API의 안정적인 부분으로 간주되지 않으며 향후 릴리스에서 변경될 수 있습니다.
views.py 를 다음과 같이 업데이트합니다.
import calendar
from django.shortcuts import render
from django.utils import timezone
def index(request):
current_year = timezone.now().year
calendar_html = calendar.HTMLCalendar().formatyear(current_year)
return render(request, 'wagtailcalendar/index.html', {
'current_year': current_year,
'calendar_html': calendar_html,
})
이제 wagtailcalendar 앱 내에 templates/wagtailcalendar/ 폴더를 만들고, 그 안에 index.html 과 calendar.css 를 다음과 같이 포함시킵니다.
{% extends "wagtailadmin/base.html" %}
{% load static %}
{% block titletag %}{{ current_year }} calendar{% endblock %}
{% block extra_css %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'css/calendar.css' %}">
{% endblock %}
{% block content %}
{% include "wagtailadmin/shared/header.html" with title="Calendar" icon="date" %}
<div class="nice-padding">
{{ calendar_html|safe }}
</div>
{% endblock %}
/* calendar.css */
table.month {
margin: 20px;
}
table.month td,
table.month th {
padding: 5px;
}
여기서는 기본 템플릿에 정의된 세 개의 블록을 재정의하고 있습니다: titletag(HTML <title> 태그의 내용을 설정), extra_css(이 페이지에 특정한 추가 CSS 스타일을 제공), 그리고 content(페이지의 주 콘텐츠 영역). 또한 표준 헤더 바 컴포넌트를 포함하고 제목과 아이콘을 설정하고 있습니다. 인식되는 아이콘 식별자 목록은 스타일 가이드를 참조하세요.
/admin/calendar/ 를 다시 방문하면 이제 Wagtail 관리자 페이지 구조 내에 달력이 표시됩니다.

메뉴 항목 추가하기¶
이제 달력 뷰는 완성되었지만, 관리자 백엔드의 다른 곳에서 접근할 방법이 없습니다. 사이드바 메뉴에 항목을 추가하기 위해 또 다른 훅인 Register Admin Menu Item을 사용하겠습니다. wagtail_hooks.py 를 다음과 같이 업데이트합니다.
from django.urls import path, reverse
from wagtail.admin.menu import MenuItem
from wagtail import hooks
from .views import index
@hooks.register('register_admin_urls')
def register_calendar_url():
return [
path('calendar/', index, name='calendar'),
]
@hooks.register('register_admin_menu_item')
def register_calendar_menu_item():
return MenuItem('Calendar', reverse('calendar'), icon_name='date')
이제 메뉴에 ‘Calendar’ 항목이 나타납니다.

메뉴 항목 그룹 추가하기¶
때로는 사이드바의 단일 메뉴 항목에 사용자 정의 뷰들을 그룹화하고 싶을 수 있습니다. 현재 달력 월만 표시하는 또 다른 뷰를 만들어 보겠습니다.
import calendar
from django.shortcuts import render
from django.utils import timezone
def index(request):
current_year = timezone.now().year
calendar_html = calendar.HTMLCalendar().formatyear(current_year)
return render(request, 'wagtailcalendar/index.html', {
'current_year': current_year,
'calendar_html': calendar_html,
})
def month(request):
current_year = timezone.now().year
current_month = timezone.now().month
calendar_html = calendar.HTMLCalendar().formatmonth(current_year, current_month)
return render(request, 'wagtailcalendar/index.html', {
'current_year': current_year,
'calendar_html': calendar_html,
})
또한 wagtail_hooks.py 를 업데이트하여 관리자 인터페이스에 URL을 등록해야 합니다.
from django.urls import path
from wagtail import hooks
from .views import index, month
@hooks.register('register_admin_urls')
def register_calendar_url():
return [
path('calendar/', index, name='calendar'),
path('calendar/month/', month, name='calendar-month'),
]
이제 달력은 /admin/calendar/month/ URL에서 볼 수 있습니다.

마지막으로, wagtail_hooks.py 를 변경하여 사용자 정의 메뉴 항목 그룹을 포함할 수 있습니다. 이는 단일 항목을 추가하는 것과 유사하지만 Menu 와 SubmenuMenuItem 이라는 두 개의 클래스를 더 가져와야 합니다.
from django.urls import path, reverse
from wagtail.admin.menu import Menu, MenuItem, SubmenuMenuItem
from wagtail import hooks
from .views import index, month
@hooks.register('register_admin_urls')
def register_calendar_url():
return [
path('calendar/', index, name='calendar'),
path('calendar/month/', month, name='calendar-month'),
]
@hooks.register('register_admin_menu_item')
def register_calendar_menu_item():
submenu = Menu(items=[
MenuItem('Calendar', reverse('calendar'), icon_name='date'),
MenuItem('Current month', reverse('calendar-month'), icon_name='date'),
])
return SubmenuMenuItem('Calendar', submenu, icon_name='date')
이제 ‘Calendar’ 항목이 메뉴 항목 그룹으로 나타납니다. 확장하면 ‘Calendar’ 항목에 두 개의 사용자 정의 메뉴 항목이 표시됩니다.

ViewSet 을 사용하여 사용자 정의 관리자 뷰 그룹화하기¶
URL 및 메뉴 항목과 함께 관리자 뷰를 등록하는 것은 Wagtail에서 일반적인 패턴입니다. 이는 종종 우리가 작업하는 모델 및 관련 아이콘과 같은 공유 속성을 가진 여러 관련 뷰를 포함합니다. 이 패턴을 지원하기 위해 Wagtail은 뷰셋(viewset) 개념을 구현합니다. 이를 통해 뷰와 해당 URL 묶음을 집합적으로 정의하고, register_admin_viewset 훅을 통해 단일 작업으로 관리자 앱에 메뉴 항목을 등록할 수 있습니다.
예를 들어, 이전 예제의 달력 뷰들을 views.py 에 ViewSet 서브클래스를 만들어 단일 메뉴 항목으로 그룹화할 수 있습니다.
from wagtail.admin.viewsets.base import ViewSet
...
class CalendarViewSet(ViewSet):
add_to_admin_menu = True
menu_label = "Calendar"
icon = "date"
# `name` 은 URL 접두사와 URL 네임스페이스 모두에 사용됩니다.
# `url_prefix` 와 `url_namespace` 를 통해 개별적으로 사용자 정의할 수 있습니다.
name = "calendar"
def get_urlpatterns(self):
return [
# 이것은 `/admin/calendar/` 에서 접근할 수 있으며
# `calendar:index` 이름으로 역-확인(reverse-resolved)될 수 있습니다.
# 이 첫 번째 URL은 메뉴 항목에 사용되지만,
# `menu_url` 속성을 재정의하여 사용자 정의할 수 있습니다.
path('', index, name='index'),
# 이것은 `/admin/calendar/month/` 에서 접근할 수 있으며
# `calendar:month` 이름으로 역-확인될 수 있습니다.
path('month/', month, name='month'),
]
그런 다음, wagtail_hooks.py 에서 register_admin_urls 와 register_admin_menu_item 훅을 제거하고, register_admin_viewset 훅으로 ViewSet 서브클래스를 등록합니다.
from .views import CalendarViewSet
@hooks.register("register_admin_viewset")
def register_viewset():
return CalendarViewSet()
두 개의 개별 훅을 사용한 이전 예제와 비교하여, 이것은 /admin/calendar/ URL로 이동하는 단일 메뉴 항목 “Calendar”를 생성합니다. 두 번째 URL은 자체 메뉴 항목을 갖지 않지만, 여전히 /admin/calendar/month/ 에서 접근할 수 있습니다. 이는 반드시 자체 메뉴 항목이 필요하지 않은 관련 뷰들을 함께 그룹화하는 데 유용합니다.
추가적인 사용자 정의는 ViewSet 문서를 참조하세요.
ViewSetGroup 을 사용하여 여러 ViewSet 결합하기¶
ViewSetGroup 클래스는 여러 ViewSet 을 최상위 메뉴 항목 내에 그룹화하는 데 사용할 수 있습니다. 예를 들어, 이전 예제의 CalendarViewSet 과 그룹화하려는 다른 뷰셋(예: EventViewSet)이 있는 경우, views.py 에 ViewSetGroup 서브클래스를 만들어 그렇게 할 수 있습니다.
from wagtail.admin.viewsets.base import ViewSetGroup
...
class AgendaViewSetGroup(ViewSetGroup):
menu_label = "Agenda"
menu_icon = "table"
# `items` 에 `ViewSet` 의 인스턴스나 서브클래스를 지정할 수 있습니다.
items = (CalendarViewSet(), EventViewSet)
그런 다음, 뷰셋에서 add_to_admin_menu 를 제거하고 wagtail_hooks.py 의 register_admin_viewset 훅을 업데이트하여 개별 뷰셋 대신 ViewSetGroup 을 등록합니다.
from .views import AgendaViewSetGroup
@hooks.register("register_admin_viewset")
def register_viewset():
return AgendaViewSetGroup()
이렇게 하면 “Agenda”라는 최상위 메뉴 항목이 생성되고, 그 아래에 “Calendar”와 “Events”와 같은 두 뷰셋의 메뉴 항목이 하위 항목으로 표시됩니다.
추가적인 사용자 정의는 ViewSetGroup 문서를 참조하세요.
관리자 뷰에 링크 추가하기¶
스니펫 (Snippets)¶
예제로 Wagtail Bakery 데모의 BreadTypeSnippet 을 사용하겠습니다.
스니펫 URL 이름은 기본적으로 wagtailsnippets_{app_label}_{model_name}:{list/edit/inspect/copy/delete} 패턴을 따릅니다.
Python에서는 get_url_name() 을 사용하여 스니펫 뷰 URL의 이름을 얻을 수 있습니다. (예: BreadTypeSnippet.get_url_name("list"))
따라서 BreadTypeSnippet URL은 템플릿에서 다음과 같이 보입니다.
{% url 'wagtailsnippets_breads_breadtype:list' %}
{% url 'wagtailsnippets_breads_breadtype:edit' object.id %}
{% url 'wagtailsnippets_breads_breadtype:inspect' object.id %}
{% url 'wagtailsnippets_breads_breadtype:copy' object.id %}
{% url 'wagtailsnippets_breads_breadtype:delete' object.id %}
페이지 (Pages)¶
새 페이지
{% url 'wagtailadmin_pages:add' content_type_app_name content_type_model_name parent_id %}
페이지 사용 현황
{% url 'wagtailadmin_pages:usage' page_id %}
페이지 수정
{% url 'wagtailadmin_pages:edit' page_id %}
페이지 삭제
{% url 'wagtailadmin_pages:delete' page_id %}
페이지 복사
{% url 'wagtailadmin_pages:copy' page_id }
이미지 (Images)¶
이미지 목록
{% url 'wagtailimages:index' %}
이미지 수정
{% url 'wagtailimages:edit' image_id %}
이미지 삭제
{% url 'wagtailimages:delete' image_id %}
새 이미지
{% url 'wagtailimages:add' %}
이미지 사용 현황
{% url 'wagtailimages:image_usage' image_id %}
AdminURLFinder¶
관리자에서 모든 모델의 URL을 찾기 위해 AdminURLFinder 클래스를 사용할 수 있습니다.
from wagtail.admin.admin_url_finder import AdminURLFinder
finder = AdminURLFinder()
finder.get_edit_url(model_instance)