Смеситель маршрутизируемых страниц
Смеситель RoutablePageMixin предоставляет удобный способ для страницы реагировать на несколько под-URL с различными представлениями. Например, раздел блога на сайте может предоставлять несколько различных типов страниц индекса по URL-адресам, таким как /blog/2013/06/, /blog/authors/bob/, /blog/tagged/python/, все из которых обслуживаются одним экземпляром страницы.
Страница, использующая Page с RoutablePageMixin, существует в дереве страниц, как и любая другая страница, но пути URL под ней проверяются на соответствие списку шаблонов. Если ни один из шаблонов не соответствует, управление передаётся подстраницам как обычно (или, в случае неудачи, выводится ошибка 404).
По умолчанию существует маршрут для r'^$', который обслуживает контент точно так же, как и обычная Page. Его можно переопределить, используя @route(r'^$') в любом другом методе наследуемого класса.
Установка
Добавьте "wagtail.contrib.routable_page" в ваш INSTALLED_APPS:
INSTALLED_APPS = [ ... "wagtail.contrib.routable_page", ]
Основы
Чтобы использовать RoutablePageMixin, вам необходимо сделать свой класс наследником как wagtail.contrib.routable_page.models.RoutablePageMixin, так и wagtail.models.Page, затем определить некоторые методы представления и декорировать их с помощью wagtail.contrib.routable_page.models.route. Эти методы представления ведут себя как обычные функции представления Django и должны возвращать объект HttpResponse; обычно это делается путём вызова django.shortcuts.render.
Вот пример 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, route
class EventIndexPage(RoutablePageMixin, Page):
# Routable pages can have fields like any other - here we would
# render the intro text on a template with {{ page.intro|richtext }}
intro = RichTextField()
@route(r'^$') # will override the default Page serving mechanism
def current_events(self, request):
"""
View function for the current events page
"""
events = EventPage.objects.live().filter(event_date__gte=datetime.date.today())
# NOTE: We can use the RoutablePageMixin.render() method to render
# the page as normal, but with some of the context values overridden
return self.render(request, context_overrides={
'title': "Current events",
'events': events,
})
@route(r'^past/$')
def past_events(self, request):
"""
View function for the past events page
"""
events = EventPage.objects.live().filter(event_date__lt=datetime.date.today())
# NOTE: We are overriding the template here, as well as few context values
return self.render(
request,
context_overrides={
'title': "Past events",
'events': events,
},
template="events/event_index_historical.html",
)
# Multiple routes!
@route(r'^year/(\d+)/$')
@route(r'^year/current/$')
def events_for_year(self, request, year=None):
"""
View function for the events for year page
"""
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': "Events for %d" % year,
'events': events,
})
@route(r'^year/(\d+)/count/$')
def count_for_year(self, request, year=None):
"""
View function that returns a simple JSON response that
includes the number of events scheduled for a specific year
"""
events = EventPage.objects.live().filter(event_date__year=year)
# NOTE: The usual template/context rendering process is irrelevant
# here, so we'll just return a HttpResponse directly
return JsonResponse({'count': events.count()})
Отображение других страниц
Ещё один способ вернуть HttpResponse — вызвать метод serve другой страницы. (Вызов собственного метода serve страницы внутри метода представления недопустим, поскольку метод представления уже вызывается внутри serve, и это создаст циклическое определение).
Например, EventIndexPage можно расширить маршрутом next/, который отображает страницу для следующего события:
@route(r'^next/$')
def next_event(self, request):
"""
Display the page for the next event
"""
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 добавляет метод reverse_subpage() к вашей модели страницы, который вы можете использовать для обращения URL-адресов. Например:
# The URL name defaults to the view method name.
>>> event_page.reverse_subpage('events_for_year', args=(2015, ))
'year/2015/'
Этот метод возвращает только часть URL-адреса внутри страницы. Чтобы получить полный URL-адрес, необходимо добавить его к значениям либо url, либо атрибута full_url на вашей странице:
>>> event_page.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/'
Изменение имён маршрутов
Имя маршрута по умолчанию соответствует имени представления. Вы можете переопределить это имя с помощью ключевого аргумента name в @route:
from wagtail.models import Page
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
class EventPage(RoutablePageMixin, Page):
...
@route(r'^year/(\d+)/$', name='year')
def events_for_year(self, request, year):
"""
View function for the events for year page
"""
...
>>> event_page.url + event_page.reverse_subpage('year', args=(2015, ))
'/events/year/2015/'
Класс RoutablePageMixin
Тег шаблона routablepageurl
© 2014-present Torchbox Ltd and individual contributors.
All rights are reserved.
Licensed under the BSD License.
https://docs.wagtail.org/en/v3.0.3/reference/contrib/routablepage.html