Смешивание страниц с маршрутизацией
Смешивание 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.core.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.core.fields import RichTextField
from wagtail.core.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.core.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/v2.16.3/reference/contrib/routablepage.html