(routable_page_mixin)= # `RoutablePageMixin` ```{eval-rst} .. module:: wagtail.contrib.routable_page ``` `RoutablePageMixin` 믹스인은 페이지가 다른 뷰로 여러 하위 URL에 응답하는 편리한 방법을 제공합니다. 예를 들어, 사이트의 블로그 섹션은 `/blog/2013/06/`, `/blog/authors/bob/`, `/blog/tagged/python/` 과 같은 URL에서 여러 유형의 색인 페이지를 제공할 수 있으며, 이 모든 페이지는 동일한 페이지 인스턴스에서 제공됩니다. `RoutablePageMixin` 을 사용하는 `Page` 는 다른 페이지와 마찬가지로 페이지 트리 내에 존재하지만, 그 아래의 URL 경로는 패턴 목록과 비교됩니다. 패턴이 일치하지 않으면 제어는 평소와 같이 하위 페이지로 전달됩니다(또는 그렇지 않으면 404 오류가 발생함). 기본적으로 `r'^$'` 에 대한 경로가 존재하며, 이는 일반 `Page` 와 똑같이 콘텐츠를 제공합니다. 이는 상속 클래스의 다른 메서드에서 `@re_path(r'^$')` 또는 `@path('')` 를 사용하여 재정의할 수 있습니다. ## 설치 `INSTALLED_APPS` 에 `"wagtail.contrib.routable_page"` 를 추가합니다. ```python INSTALLED_APPS = [ ... "wagtail.contrib.routable_page", ] ``` ## 기본 사항 `RoutablePageMixin` 을 사용하려면 클래스가 {class}`wagtail.contrib.routable_page.models.RoutablePageMixin` 과 {class}`wagtail.models.Page` 를 모두 상속하도록 한 다음, `path` 또는 `re_path` 로 일부 뷰 메서드를 정의하고 데코레이트해야 합니다. 이러한 뷰 메서드는 일반 Django 뷰 함수처럼 동작하며 `HttpResponse` 객체를 반환해야 합니다. 일반적으로 `django.shortcuts.render` 를 호출하여 수행됩니다. `wagtail.contrib.routable_page.models.path` 의 `path` 및 `re_path` 데코레이터는 [Django `django.urls` `path` 및 `re_path` 함수](inv:django#topics/http/urls)와 유사합니다. 전자는 일반 경로 및 변환기 사용을 허용하고 후자는 URL 패턴을 정규식으로 지정할 수 있도록 합니다. 다음은 `EventIndexPage` 에 세 가지 뷰가 있는 예시입니다. `EventPage` 모델에 `event_date` 필드가 다른 곳에 정의되어 있다고 가정합니다. ```python import datetime from django.http import JsonResponse from wagtail.fields import RichTextField from wagtail.models import Page from wagtail.contrib.routable_page.models import RoutablePageMixin, path, re_path class EventIndexPage(RoutablePageMixin, Page): # 라우팅 가능한 페이지는 다른 페이지와 마찬가지로 필드를 가질 수 있습니다. 여기서는 # intro 텍스트를 템플릿에 {{ page.intro|richtext }}로 렌더링합니다. intro = RichTextField() @path('') # 기본 페이지 제공 메커니즘을 재정의합니다. def current_events(self, request): """ 현재 이벤트 페이지에 대한 뷰 함수 """ events = EventPage.objects.live().filter(event_date__gte=datetime.date.today()) # 참고: RoutablePageMixin.render() 메서드를 사용하여 # 일부 컨텍스트 값을 재정의하여 페이지를 정상적으로 렌더링할 수 있습니다. return self.render(request, context_overrides={ 'title': "현재 이벤트", 'events': events, }) @path('past/') def past_events(self, request): """ 과거 이벤트 페이지에 대한 뷰 함수 """ events = EventPage.objects.live().filter(event_date__lt=datetime.date.today()) # 참고: 여기서는 템플릿을 재정의하고 있으며, 몇 가지 컨텍스트 값도 재정의하고 있습니다. return self.render( request, context_overrides={ 'title': "과거 이벤트", 'events': events, }, template="events/event_index_historical.html", ) # 여러 경로! @path('year//') @path('year/current/') def events_for_year(self, request, year=None): """ 연도별 이벤트 페이지에 대한 뷰 함수 """ if year is None: year = datetime.date.today().year events = EventPage.objects.live().filter(event_date__year=year) return self.render(request, context_overrides={ 'title': "%d년 이벤트" % year, 'events': events, }) @re_path(r'^year/(\d+)/count/$') def count_for_year(self, request, year=None): """ 특정 연도에 예약된 이벤트 수를 포함하는 간단한 JSON 응답을 반환하는 뷰 함수 """ events = EventPage.objects.live().filter(event_date__year=year) # 참고: 일반적인 템플릿/컨텍스트 렌더링 프로세스는 여기서는 관련이 없습니다. # 따라서 HttpResponse를 직접 반환합니다. return JsonResponse({'count': events.count()}) ``` ### 다른 페이지 렌더링 `HttpResponse` 를 반환하는 또 다른 방법은 다른 페이지의 `serve` 메서드를 호출하는 것입니다. (뷰 메서드 내에서 페이지 자체의 `serve` 메서드를 호출하는 것은 유효하지 않습니다. 뷰 메서드가 이미 `serve` 내에서 호출되고 있으며, 이는 순환 정의를 생성하기 때문입니다). 예를 들어, `EventIndexPage` 는 다음 이벤트에 대한 페이지를 표시하는 `next/` 경로로 확장될 수 있습니다. ```python @path('next/') def next_event(self, request): """ 다음 이벤트에 대한 페이지 표시 """ future_events = EventPage.objects.live().filter(event_date__gt=datetime.date.today()) next_event = future_events.order_by('event_date').first() return next_event.serve(request) ``` ### URL 역변환 RoutablePageMixin은 URL을 역변환하는 데 사용할 수 있는 reverse_subpage 메서드를 페이지 모델에 추가합니다. 예를 들어: ```python # URL 이름은 기본적으로 뷰 메서드 이름입니다. >>> event_page.reverse_subpage('events_for_year', args=(2015, )) 'year/2015/' ``` 이 메서드는 페이지 내의 URL 부분만 반환합니다. 전체 URL을 얻으려면 {meth}`~wagtail.models.Page.get_url` 메서드 또는 페이지의 {attr}`~wagtail.models.Page.full_url` 속성 값에 추가해야 합니다. ```python >>> event_page.get_url() + event_page.reverse_subpage('events_for_year', args=(2015, )) '/events/year/2015/' >>> event_page.full_url + event_page.reverse_subpage('events_for_year', args=(2015, )) 'http://example.com/events/year/2015/' ``` ### 경로 이름 변경 경로 이름은 기본적으로 뷰의 이름입니다. `@path` 또는 `re_path` 의 `name` 키워드 인수를 사용하여 이 이름을 재정의할 수 있습니다. ```python from wagtail.models import Page from wagtail.contrib.routable_page.models import RoutablePageMixin, re_path class EventPage(RoutablePageMixin, Page): ... @re_path(r'^year/(\d+)/$', name='year') def events_for_year(self, request, year): """ 연도별 이벤트 페이지에 대한 뷰 함수 """ ... ``` ```python >>> event_page.url + event_page.reverse_subpage('year', args=(2015, )) '/events/year/2015/' ``` ## `RoutablePageMixin` 클래스 ```{eval-rst} .. automodule:: wagtail.contrib.routable_page.models .. autoclass:: RoutablePageMixin .. automethod:: route 이 메서드는 기본 :meth:`Page.route() ` 메서드를 재정의하여 요청을 적절한 뷰 메서드로 라우팅합니다. Django가 :attr:`request.resolver_match ` 를 설정하는 것과 동일한 방식으로 하위 URL 라우팅 정보를 다운스트림에서 사용할 수 있도록 요청 객체에 ``routable_resolver_match`` 를 설정합니다. .. automethod:: render .. automethod:: get_subpage_urls .. automethod:: resolve_subpage 예시: .. code-block:: python view, args, kwargs = page.resolve_subpage('/past/') response = view(request, *args, **kwargs) .. automethod:: reverse_subpage 예시: .. code-block:: python url = page.url + page.reverse_subpage('events_for_year', kwargs={'year': '2014'}) ``` (routablepageurl_template_tag)= ## `routablepageurl` 템플릿 태그 ```{eval-rst} .. currentmodule:: wagtail.contrib.routable_page.templatetags.wagtailroutablepage_tags .. autofunction:: routablepageurl ``` 예시: ```html+django {% load wagtailroutablepage_tags %} {% routablepageurl page "feed" %} {% routablepageurl page "archive" 2014 08 14 %} {% routablepageurl page "food" foo="bar" baz="quux" %} ```