(adding_reports)= # 보고서 추가 보고서는 특정 쿼리와 일치하는 페이지 또는 스니펫과 같은 비페이지 모델 목록이 있는 뷰입니다. 보고서는 이러한 목록을 스프레드시트 형식으로 내보낼 수도 있습니다. 보고서는 _보고서_ 하위 메뉴에서 찾을 수 있습니다. 기본적으로 _잠긴 페이지_ 보고서가 제공되어 사이트의 잠긴 페이지에 대한 개요를 볼 수 있습니다. Wagtail 관리자에서 두 가지 기본 클래스를 사용하여 사용자 지정 보고서를 만들 수 있습니다. - `wagtail.admin.views.reports.ReportView` - 기본 목록(단일 열 포함) 및 스프레드시트 내보내기 기능을 제공합니다. - `wagtail.admin.views.reports.PageReportView` - `ReportView` 를 확장하고 페이지 목록에 적합한 기본 필드 세트를 제공합니다. ## 보고 참조 ### `get_queryset` 보고서를 정의하기 위해 사용자 지정할 가장 중요한 속성 및 메서드는 다음과 같습니다. ```{eval-rst} .. method:: get_queryset(self) ``` 이것은 보고서에 대한 페이지 또는 기타 모델의 쿼리셋을 검색합니다. 아래 두 가지 예시가 있습니다. ```python # /views.py from wagtail.admin.views.reports import ReportView, PageReportView from wagtail.models import Page from .models import MySnippetModel class UnpublishedChangesReportView(PageReportView): # 기본적으로 일반 페이지 필드를 포함합니다. def get_queryset(self): return Page.objects.filter(has_unpublished_changes=True) class CustomModelReport(ReportView): # 단일 열로 문자열 표현만 포함합니다. def get_queryset(self): return MySnippetModel.objects.all() ``` ### 기타 속성 ```{eval-rst} .. attribute:: template_name (문자열) 보고서 뷰를 렌더링하는 데 사용되는 템플릿으로, 기본값은\ ``"wagtailadmin/reports/base_report.html"``\ 입니다. 이 템플릿은 뷰의 골격만 제공하며, 목록 테이블 자체는 제공하지 않습니다. 목록 테이블은\ ``results_template_name``\(아래 참조)으로 지정된 별도의 템플릿에 구현되어\ ``{% include %}``\ 를 통해 렌더링되어야 합니다. 전체 뷰를 사용자 지정하려는 경우가 아니면 이 템플릿을 변경할 필요는 거의 없습니다. 목록을 사용자 지정하려면 대신\ ``results_template_name``\ 을 변경하십시오. .. attribute:: results_template_name (문자열) 목록 테이블을 렌더링하는 데 사용되는 템플릿입니다. ``ReportView``\ 의 경우, 이 값은 기본적으로\ ``"wagtailadmin/reports/base_report_results.html"``\ 이며,\ ``wagtail.admin.ui.tables``\ 프레임워크 사용을 지원합니다. ``PageReportView``\ 의 경우, 이 값은 기본적으로\ ``"wagtailadmin/reports/base_page_report_results.html"``\ 이며, 탐색기 뷰를 기반으로 한 기본 테이블 레이아웃을 제공하고 작업 버튼, 제목, 마지막 업데이트 시간, 상태 및 모든 페이지의 특정 유형을 표시합니다. 이 예제에서는 나중에 이 템플릿을 새 템플릿으로 변경할 것입니다. .. attribute:: page_title (문자열) 보고서의 이름으로, 헤더에 표시됩니다. 이 예제에서는\ ``"게시되지 않은 변경 사항이 있는 페이지"``\로 설정합니다. .. attribute:: header_icon (문자열) 표준 Wagtail 아이콘 이름을 사용하는 아이콘의 이름입니다. 예를 들어, 잠긴 페이지 뷰는\ ``"locked"``\ 를 사용하며, 이 예제 보고서의 경우\ ``'doc-empty-inverse'``\ 로 설정합니다. .. attribute:: index_url_name (문자열) 보고서 뷰에 등록된 URL 패턴의 이름입니다. .. attribute:: index_results_url_name (문자열) 결과 뷰(``.as_view(results_only=True)``\ 가 있는 보고서 뷰)에 등록된 URL 패턴의 이름입니다. ``` ### 스프레드시트 내보내기 ```{eval-rst} .. attribute:: list_export (목록) 스프레드시트 뷰에서 열로 내보내지는 각 모델의 필드/속성 목록입니다. ``ReportView``\ 의 경우 기본적으로 비어 있으며, ``PageReportView``\ 의 경우 목록 필드에 해당합니다: 모든 페이지의 제목, 마지막 업데이트 시간, 상태 및 특정 유형. 이 예제에서는 페이지가 마지막으로 게시된 시점을 알고 싶을 수 있으므로\ ``list_export``\ 를 다음과 같이 설정합니다. ``list_export = PageReportView.list_export + ['last_published_at']`` .. attribute:: export_headings (사전) 스프레드시트 열에 대한 제목을 수동으로 지정하려는 ``list_export``\ 의 모든 필드/속성 및 해당 제목의 사전입니다. 지정되지 않은 경우, 제목은 해당되는 경우 필드\ ``verbose_name``\ 에서 가져오고, 그렇지 않으면 속성 문자열에서 가져옵니다. 이 예제에서는\ ``last_published_at``\ 이 자동으로\ ``"마지막 게시 시간"``\ 이라는 제목을 얻지만, 간단한 "마지막 게시"가 더 깔끔해 보입니다. ``export_headings``\ 를 설 ``export_headings = dict(last_published_at='마지막 게시', **PageReportView.export_headings)`` .. attribute:: custom_value_preprocess (사전) ``(value_class_1, value_class_2, ...)``\ 튜플을\ ``{export_format: preprocessing_function}``\ 사전으로 매핑하는 사전으로, 특정 클래스(또는 해당 서브클래스)의 필드 값을 내보낼 때 사용자 지정 전처리 함수를 적용할 수 있습니다. 지정되지 않은 경우(및 ``ReportView.custom_field_preprocess``\ 도 함수를 지정하지 않은 경우) ``force_str``\ 이 사용됩니다. 전처리를 방지하려면 preprocessing_function을\ ``None``\ 으로 설정하십시오. .. attribute:: custom_field_preprocess (사전) ``field_name``\ 문자열을\ ``{export_format: preprocessing_function}``\ 사전으로 매핑하는 사전으로, 특정 클래스(또는 해당 서브클래스)의 필드 값을 내보낼 때 사용자 지정 전처리 함수를 적용할 수 있습니다. 이는\ ``ReportView.custom_value_preprocess``\ 에 지정된 함수보다 우선합니다. 지정되지 않은 경우(및\ ``ReportView.custom_value_preprocess``\ 도 함수를 지정하지 않은 경우) ``force_str``\ 이 사용됩니다. 전처리를 방지하려면 preprocessing_function을\ ``None``\ 으로 설정하십시오. ``` ## 게시되지 않은 변경 사항이 있는 페이지에 대한 보고서 예시 이 예제에서는 게시되지 않은 변경 사항이 있는 페이지를 보여주는 보고서를 추가합니다. URL 패턴에 `unpublished_changes_report` 이름을 사용하여 이 뷰를 등록합니다. ```python # /views.py from wagtail.admin.views.reports import PageReportView class UnpublishedChangesReportView(PageReportView): index_url_name = "unpublished_changes_report" index_results_url_name = "unpublished_changes_report_results" ``` ### 템플릿 사용자 지정 이 예제 "게시되지 않은 변경 사항이 있는 페이지" 보고서의 경우, 각 페이지의 마지막 게시 날짜를 보여주는 추가 열을 목록 템플릿에 추가합니다. 이를 위해 `wagtailadmin/reports/base_page_report_results.html` 및 `wagtailadmin/reports/listing/_list_page_report.html` 두 템플릿을 확장합니다. ```html+django {# /templates/reports/unpublished_changes_report_results.html #} {% extends 'wagtailadmin/reports/base_page_report_results.html' %} {% block results %} {% include 'reports/include/_list_unpublished_changes.html' %} {% endblock %} {% block no_results_message %}

게시되지 않은 변경 사항이 있는 페이지가 없습니다.

{% endblock %} ``` ```html+django {# /templates/reports/include/_list_unpublished_changes.html #} {% extends 'wagtailadmin/reports/listing/_list_page_report.html' %} {% block extra_columns %} 마지막 게시 {% endblock %} {% block extra_page_data %} {{ page.last_published_at }} {% endblock %} ``` 마지막으로 `UnpublishedChangesReportView.results_template_name` 을 이 새 템플릿인 `'reports/unpublished_changes_report_results.html'` 로 설정합니다. ### 메뉴 항목 및 관리자 URL 추가 새 보고서에 대한 메뉴 항목을 _보고서_ 하위 메뉴에 추가하려면 `register_reports_menu_item` 훅(참조: [보고서 메뉴 항목 등록](register_reports_menu_item))을 사용해야 합니다. 보고서에 대한 관리자 URL을 추가하려면 `register_admin_urls` 훅(참조: [관리자 URL 등록](register_admin_urls))을 사용해야 합니다. 다음과 같이 수행할 수 있습니다. ```python # /wagtail_hooks.py from django.urls import path, reverse from wagtail.admin.menu import AdminOnlyMenuItem from wagtail import hooks from .views import UnpublishedChangesReportView @hooks.register('register_reports_menu_item') def register_unpublished_changes_report_menu_item(): return AdminOnlyMenuItem("게시되지 않은 변경 사항이 있는 페이지", reverse('unpublished_changes_report'), icon_name=UnpublishedChangesReportView.header_icon, order=700) @hooks.register('register_admin_urls') def register_unpublished_changes_report_url(): return [ path('reports/unpublished-changes/', UnpublishedChangesReportView.as_view(), name='unpublished_changes_report'), path('reports/unpublished-changes/results/', UnpublishedChangesReportView.as_view(results_only=True), name='unpublished_changes_report_results'), ] ``` 여기서는 `AdminOnlyMenuItem` 클래스를 사용하여 보고서 아이콘이 슈퍼유저에게만 표시되도록 합니다. 모든 사용자에게 보고서를 표시하려면 `MenuItem` 으로 바꿀 수 있습니다. ### 권한 제한 설정 메뉴 항목이 숨겨져 있더라도 모든 사용자가 보고서의 URL에 직접 방문할 수 있으므로 보고서 뷰 자체에 권한 제한을 설정해야 합니다. 이는 기존 `UnpublishedChangesReportView` 뷰에 `dispatch` 메서드를 추가하여 수행할 수 있습니다. ```python # 기존 UnpublishedChangesReportView 뷰에 아래 dispatch 메서드를 추가합니다. def dispatch(self, request, *args, **kwargs): if not self.request.user.is_superuser: return permission_denied(request) return super().dispatch(request, *args, **kwargs) ``` ### 전체 코드 ```python # /views.py from wagtail.admin.auth import permission_denied from wagtail.admin.views.reports import PageReportView from wagtail.models import Page class UnpublishedChangesReportView(PageReportView): index_url_name = "unpublished_changes_report" index_results_url_name = "unpublished_changes_report_results" header_icon = 'doc-empty-inverse' results_template_name = 'reports/unpublished_changes_report_results.html' page_title = "게시되지 않은 변경 사항이 있는 페이지" list_export = PageReportView.list_export + ['last_published_at'] export_headings = dict(last_published_at='마지막 게시', **PageReportView.export_headings) def get_queryset(self): return Page.objects.filter(has_unpublished_changes=True) def dispatch(self, request, *args, **kwargs): if not self.request.user.is_superuser: return permission_denied(request) return super().dispatch(request, *args, **kwargs) ``` ```python # /wagtail_hooks.py from django.urls import path, reverse from wagtail.admin.menu import AdminOnlyMenuItem from wagtail import hooks from .views import UnpublishedChangesReportView @hooks.register('register_reports_menu_item') def register_unpublished_changes_report_menu_item(): return AdminOnlyMenuItem("게시되지 않은 변경 사항이 있는 페이지", reverse('unpublished_changes_report'), icon_name=UnpublishedChangesReportView.header_icon, order=700) @hooks.register('register_admin_urls') def register_unpublished_changes_report_url(): return [ path('reports/unpublished-changes/', UnpublishedChangesReportView.as_view(), name='unpublished_changes_report'), path('reports/unpublished-changes/results/', UnpublishedChangesReportView.as_view(results_only=True), name='unpublished_changes_report_results'), ] ``` ```html+django {# /templates/reports/unpublished_changes_report_results.html #} {% extends 'wagtailadmin/reports/base_page_report_results.html' %} {% block results %} {% include 'reports/include/_list_unpublished_changes.html' %} {% endblock %} {% block no_results_message %}

게시되지 않은 변경 사항이 있는 페이지가 없습니다.

{% endblock %} ``` ```html+django {# /templates/reports/include/_list_unpublished_changes.html #} {% extends 'wagtailadmin/reports/listing/_list_page_report.html' %} {% block extra_columns %} 마지막 게시 {% endblock %} {% block extra_page_data %} {{ page.last_published_at }} {% endblock %} ```