RoutablePageMixin

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" 를 추가합니다.

INSTALLED_APPS = [
    ...

    "wagtail.contrib.routable_page",
]

기본 사항

RoutablePageMixin 을 사용하려면 클래스가 wagtail.contrib.routable_page.models.RoutablePageMixinwagtail.models.Page 를 모두 상속하도록 한 다음, path 또는 re_path 로 일부 뷰 메서드를 정의하고 데코레이트해야 합니다.

이러한 뷰 메서드는 일반 Django 뷰 함수처럼 동작하며 HttpResponse 객체를 반환해야 합니다. 일반적으로 django.shortcuts.render 를 호출하여 수행됩니다.

wagtail.contrib.routable_page.models.pathpathre_path 데코레이터는 Django django.urls pathre_path 함수와 유사합니다. 전자는 일반 경로 및 변환기 사용을 허용하고 후자는 URL 패턴을 정규식으로 지정할 수 있도록 합니다.

다음은 EventIndexPage 에 세 가지 뷰가 있는 예시입니다. EventPage 모델에 event_date 필드가 다른 곳에 정의되어 있다고 가정합니다.

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/<int: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/ 경로로 확장될 수 있습니다.

@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 메서드를 페이지 모델에 추가합니다. 예를 들어:

    # URL 이름은 기본적으로 뷰 메서드 이름입니다.
    >>> event_page.reverse_subpage('events_for_year', args=(2015, ))
    'year/2015/'

이 메서드는 페이지 내의 URL 부분만 반환합니다. 전체 URL을 얻으려면 get_url() 메서드 또는 페이지의 full_url 속성 값에 추가해야 합니다.

>>> 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_pathname 키워드 인수를 사용하여 이 이름을 재정의할 수 있습니다.

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):
        """
        연도별 이벤트 페이지에 대한 뷰 함수
        """
        ...
>>> event_page.url + event_page.reverse_subpage('year', args=(2015, ))
'/events/year/2015/'

RoutablePageMixin 클래스

class wagtail.contrib.routable_page.models.RoutablePageMixin

This class can be mixed in to a Page model, allowing extra routes to be added to it.

route(request, path_components)

This hooks the subpage URLs into Wagtail’s routing.

이 메서드는 기본 Page.route() 메서드를 재정의하여 요청을 적절한 뷰 메서드로 라우팅합니다.

Django가 request.resolver_match 를 설정하는 것과 동일한 방식으로 하위 URL 라우팅 정보를 다운스트림에서 사용할 수 있도록 요청 객체에 routable_resolver_match 를 설정합니다.

render(request, *args, template=None, context_overrides=None, **kwargs)

This method replicates what Page.serve() usually does when RoutablePageMixin is not used. By default, Page.get_template() is called to derive the template to use for rendering, and Page.get_context() is always called to gather the data to be included in the context.

You can use the context_overrides keyword argument as a shortcut to override or add new values to the context. For example:

@path('') # override the default route
def upcoming_events(self, request):
    return self.render(request, context_overrides={
        'title': "Current events",
        'events': EventPage.objects.live().future(),
    })

You can also use the template argument to specify an alternative template to use for rendering. For example:

@path('past/')
def past_events(self, request):
    return self.render(
        request,
        context_overrides={
            'title': "Past events",
            'events': EventPage.objects.live().past(),
        },
        template="events/event_index_historical.html",
    )
classmethod get_subpage_urls()
resolve_subpage(path)

This method takes a URL path and finds the view to call.

예시:

view, args, kwargs = page.resolve_subpage('/past/')
response = view(request, *args, **kwargs)
reverse_subpage(name, args=None, kwargs=None)

This method takes a route name/arguments and returns a URL path.

예시:

url = page.url + page.reverse_subpage('events_for_year', kwargs={'year': '2014'})

routablepageurl 템플릿 태그

wagtail.contrib.routable_page.templatetags.wagtailroutablepage_tags.routablepageurl(context, page, url_name, *args, **kwargs)

routablepageurl is similar to pageurl, but works with pages using RoutablePageMixin. It behaves like a hybrid between the built-in reverse, and pageurl from Wagtail.

page is the RoutablePage that URLs will be generated from.

url_name is a URL name defined in page.subpage_urls.

Positional arguments and keyword arguments should be passed as normal positional arguments and keyword arguments.

예시:

{% load wagtailroutablepage_tags %}

{% routablepageurl page "feed" %}
{% routablepageurl page "archive" 2014 08 14 %}
{% routablepageurl page "food" foo="bar" baz="quux" %}