Initial commit
This commit is contained in:
0
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__init__.py
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/apps.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/apps.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/models.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/models.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/tests.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/__pycache__/tests.cpython-310.pyc
vendored
Normal file
Binary file not shown.
8
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/apps.py
vendored
Normal file
8
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/apps.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class WagtailRoutablePageAppConfig(AppConfig):
|
||||
name = "wagtail.contrib.routable_page"
|
||||
label = "wagtailroutablepage"
|
||||
verbose_name = _("Wagtail routablepage")
|
||||
228
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/models.py
vendored
Normal file
228
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/models.py
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
import logging
|
||||
from functools import partial
|
||||
|
||||
from django.core.checks import Warning
|
||||
from django.http import Http404
|
||||
from django.template.response import TemplateResponse
|
||||
from django.urls import URLResolver
|
||||
from django.urls import path as path_func
|
||||
from django.urls import re_path as re_path_func
|
||||
from django.urls.resolvers import RegexPattern, RoutePattern
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.url_routing import RouteResult
|
||||
|
||||
_creation_counter = 0
|
||||
|
||||
logger = logging.getLogger("wagtail.routablepage")
|
||||
|
||||
|
||||
def _path(pattern, name=None, func=None):
|
||||
def decorator(view_func):
|
||||
global _creation_counter
|
||||
_creation_counter += 1
|
||||
|
||||
# Make sure page has _routablepage_routes attribute
|
||||
if not hasattr(view_func, "_routablepage_routes"):
|
||||
view_func._routablepage_routes = []
|
||||
|
||||
# Add new route to view
|
||||
view_func._routablepage_routes.append(
|
||||
(
|
||||
func(pattern, view_func, name=(name or view_func.__name__)),
|
||||
_creation_counter,
|
||||
)
|
||||
)
|
||||
|
||||
return view_func
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
re_path = partial(_path, func=re_path_func)
|
||||
path = partial(_path, func=path_func)
|
||||
|
||||
# Make route an alias of re_path for backwards compatibility.
|
||||
route = re_path
|
||||
|
||||
|
||||
class RoutablePageMixin:
|
||||
"""
|
||||
This class can be mixed in to a Page model, allowing extra routes to be
|
||||
added to it.
|
||||
"""
|
||||
|
||||
@path("")
|
||||
def index_route(self, request, *args, **kwargs):
|
||||
request.is_preview = getattr(request, "is_preview", False)
|
||||
|
||||
return TemplateResponse(
|
||||
request,
|
||||
self.get_template(request, *args, **kwargs),
|
||||
self.get_context(request, *args, **kwargs),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_subpage_urls(cls):
|
||||
routes = []
|
||||
|
||||
# Loop over this class's defined routes, in method resolution order.
|
||||
# Routes defined in the immediate class take precedence, followed by
|
||||
# immediate superclass and so on
|
||||
for klass in cls.__mro__:
|
||||
routes_for_class = []
|
||||
for val in klass.__dict__.values():
|
||||
if hasattr(val, "_routablepage_routes"):
|
||||
routes_for_class.extend(val._routablepage_routes)
|
||||
|
||||
# sort routes by _creation_counter so that ones earlier in the class definition
|
||||
# take precedence
|
||||
routes_for_class.sort(key=lambda route: route[1])
|
||||
|
||||
routes.extend(route[0] for route in routes_for_class)
|
||||
|
||||
return tuple(routes)
|
||||
|
||||
@classmethod
|
||||
def get_resolver(cls):
|
||||
if "_routablepage_urlresolver" not in cls.__dict__:
|
||||
subpage_urls = cls.get_subpage_urls()
|
||||
cls._routablepage_urlresolver = URLResolver(
|
||||
RegexPattern(r"^/"), subpage_urls
|
||||
)
|
||||
|
||||
return cls._routablepage_urlresolver
|
||||
|
||||
@classmethod
|
||||
def check(cls, **kwargs):
|
||||
errors = super().check(**kwargs)
|
||||
errors.extend(cls._check_path_with_regex())
|
||||
return errors
|
||||
|
||||
@classmethod
|
||||
def _check_path_with_regex(cls):
|
||||
routes = cls.get_subpage_urls()
|
||||
errors = []
|
||||
for route in routes:
|
||||
if isinstance(route.pattern, RoutePattern):
|
||||
pattern = route.pattern._route
|
||||
if (
|
||||
"(?P<" in pattern
|
||||
or pattern.startswith("^")
|
||||
or pattern.endswith("$")
|
||||
):
|
||||
errors.append(
|
||||
Warning(
|
||||
(
|
||||
f"Your URL pattern {route.name or route.callback.__name__} has a "
|
||||
"route that contains '(?P<', begins with a '^', or ends with a '$'."
|
||||
),
|
||||
hint="Decorate your view with re_path if you want to use regexp.",
|
||||
obj=cls,
|
||||
id="wagtailroutablepage.W001",
|
||||
)
|
||||
)
|
||||
return errors
|
||||
|
||||
def reverse_subpage(self, name, args=None, kwargs=None):
|
||||
"""
|
||||
This method takes a route name/arguments and returns a URL path.
|
||||
"""
|
||||
args = args or []
|
||||
kwargs = kwargs or {}
|
||||
|
||||
return self.get_resolver().reverse(name, *args, **kwargs)
|
||||
|
||||
def resolve_subpage(self, path):
|
||||
"""
|
||||
This method takes a URL path and finds the view to call.
|
||||
"""
|
||||
resolver_match = self.get_resolver().resolve(path)
|
||||
|
||||
# Bind the method
|
||||
resolver_match.func = resolver_match.func.__get__(self, type(self))
|
||||
|
||||
return resolver_match
|
||||
|
||||
def route(self, request, path_components):
|
||||
"""
|
||||
This hooks the subpage URLs into Wagtail's routing.
|
||||
"""
|
||||
if self.live:
|
||||
try:
|
||||
path = "/"
|
||||
if path_components:
|
||||
path += "/".join(path_components) + "/"
|
||||
|
||||
resolver_match = self.resolve_subpage(path)
|
||||
request.routable_resolver_match = resolver_match
|
||||
view, args, kwargs = resolver_match
|
||||
return RouteResult(self, args=(view, args, kwargs))
|
||||
except Http404:
|
||||
pass
|
||||
|
||||
return super().route(request, path_components)
|
||||
|
||||
def serve(self, request, view=None, args=None, kwargs=None):
|
||||
if args is None:
|
||||
args = []
|
||||
if kwargs is None:
|
||||
kwargs = {}
|
||||
if view is None:
|
||||
return super().serve(request, *args, **kwargs)
|
||||
return view(request, *args, **kwargs)
|
||||
|
||||
def render(self, 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:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@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:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@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",
|
||||
)
|
||||
"""
|
||||
if template is None:
|
||||
template = self.get_template(request, *args, **kwargs)
|
||||
context = self.get_context(request, *args, **kwargs)
|
||||
context.update(context_overrides or {})
|
||||
return TemplateResponse(request, template, context)
|
||||
|
||||
def serve_preview(self, request, mode_name):
|
||||
view, args, kwargs = self.resolve_subpage("/")
|
||||
return view(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RoutablePage(RoutablePageMixin, Page):
|
||||
"""
|
||||
This class extends Page by adding methods which allows extra routes to be
|
||||
added to it.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
0
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/templatetags/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/templatetags/__init__.py
vendored
Normal file
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,28 @@
|
||||
from django import template
|
||||
|
||||
from wagtail.models import Site
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def 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.
|
||||
"""
|
||||
request = context["request"]
|
||||
site = Site.find_for_request(request)
|
||||
base_url = page.relative_url(site, request)
|
||||
routed_url = page.reverse_subpage(url_name, args=args, kwargs=kwargs)
|
||||
if not base_url.endswith("/"):
|
||||
base_url += "/"
|
||||
return base_url + routed_url
|
||||
517
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/tests.py
vendored
Normal file
517
env/lib/python3.10/site-packages/wagtail/contrib/routable_page/tests.py
vendored
Normal file
@@ -0,0 +1,517 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.core import checks
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import path
|
||||
from django.urls.exceptions import NoReverseMatch
|
||||
|
||||
from wagtail.contrib.routable_page.templatetags.wagtailroutablepage_tags import (
|
||||
routablepageurl,
|
||||
)
|
||||
from wagtail.models import Page, Site
|
||||
from wagtail.test.routablepage.models import (
|
||||
RoutablePageTest,
|
||||
RoutablePageWithOverriddenIndexRouteTest,
|
||||
)
|
||||
|
||||
|
||||
class TestRoutablePage(TestCase):
|
||||
model = RoutablePageTest
|
||||
|
||||
def setUp(self):
|
||||
self.home_page = Page.objects.get(id=2)
|
||||
self.routable_page = self.home_page.add_child(
|
||||
instance=self.model(
|
||||
title="Routable Page",
|
||||
live=True,
|
||||
)
|
||||
)
|
||||
|
||||
def test_resolve_index_route_view(self):
|
||||
view, args, kwargs = self.routable_page.resolve_subpage("/")
|
||||
|
||||
self.assertEqual(view, self.routable_page.index_route)
|
||||
self.assertEqual(args, ())
|
||||
self.assertEqual(kwargs, {})
|
||||
|
||||
def test_resolve_archive_by_year_view(self):
|
||||
view, args, kwargs = self.routable_page.resolve_subpage("/archive/year/2014/")
|
||||
|
||||
self.assertEqual(view, self.routable_page.archive_by_year)
|
||||
self.assertEqual(args, ("2014",))
|
||||
self.assertEqual(kwargs, {})
|
||||
|
||||
def test_resolve_archive_by_author_view(self):
|
||||
view, args, kwargs = self.routable_page.resolve_subpage(
|
||||
"/archive/author/joe-bloggs/"
|
||||
)
|
||||
|
||||
self.assertEqual(view, self.routable_page.archive_by_author)
|
||||
self.assertEqual(args, ())
|
||||
self.assertEqual(kwargs, {"author_slug": "joe-bloggs"})
|
||||
|
||||
def test_resolve_archive_by_title_view(self):
|
||||
view, args, kwargs = self.routable_page.resolve_subpage(
|
||||
"/archive/title/some-title/"
|
||||
)
|
||||
|
||||
self.assertEqual(view, self.routable_page.archive_by_title)
|
||||
self.assertEqual(args, ())
|
||||
self.assertEqual(kwargs, {"title": "some-title"})
|
||||
|
||||
def test_resolve_archive_by_category_view(self):
|
||||
view, args, kwargs = self.routable_page.resolve_subpage(
|
||||
"/archive/category/some-category/"
|
||||
)
|
||||
|
||||
self.assertEqual(view, self.routable_page.archive_by_category)
|
||||
self.assertEqual(args, ())
|
||||
self.assertEqual(kwargs, {"category_slug": "some-category"})
|
||||
|
||||
def test_resolve_external_view(self):
|
||||
view, args, kwargs = self.routable_page.resolve_subpage("/external/joe-bloggs/")
|
||||
|
||||
self.assertEqual(view, self.routable_page.external_view)
|
||||
self.assertEqual(args, ("joe-bloggs",))
|
||||
self.assertEqual(kwargs, {})
|
||||
|
||||
def test_resolve_external_view_other_route(self):
|
||||
view, args, kwargs = self.routable_page.resolve_subpage("/external-no-arg/")
|
||||
|
||||
self.assertEqual(view, self.routable_page.external_view)
|
||||
self.assertEqual(args, ())
|
||||
self.assertEqual(kwargs, {})
|
||||
|
||||
def test_reverse_index_route_view(self):
|
||||
url = self.routable_page.reverse_subpage("index_route")
|
||||
|
||||
self.assertEqual(url, "")
|
||||
|
||||
def test_reverse_archive_by_year_view(self):
|
||||
url = self.routable_page.reverse_subpage("archive_by_year", args=("2014",))
|
||||
|
||||
self.assertEqual(url, "archive/year/2014/")
|
||||
|
||||
def test_reverse_archive_by_author_view(self):
|
||||
url = self.routable_page.reverse_subpage(
|
||||
"archive_by_author", kwargs={"author_slug": "joe-bloggs"}
|
||||
)
|
||||
|
||||
self.assertEqual(url, "archive/author/joe-bloggs/")
|
||||
|
||||
def test_reverse_archive_by_title_view(self):
|
||||
url = self.routable_page.reverse_subpage(
|
||||
"archive_by_title", kwargs={"title": "some-title"}
|
||||
)
|
||||
|
||||
self.assertEqual(url, "archive/title/some-title/")
|
||||
|
||||
def test_reverse_overridden_name(self):
|
||||
url = self.routable_page.reverse_subpage("name_overridden")
|
||||
|
||||
self.assertEqual(url, "override-name-test/")
|
||||
|
||||
def test_reverse_overridden_name_default_doesnt_work(self):
|
||||
with self.assertRaises(NoReverseMatch):
|
||||
self.routable_page.reverse_subpage("override_name_test")
|
||||
|
||||
def test_reverse_external_view(self):
|
||||
url = self.routable_page.reverse_subpage("external_view", args=("joe-bloggs",))
|
||||
|
||||
self.assertEqual(url, "external/joe-bloggs/")
|
||||
|
||||
def test_reverse_external_view_other_route(self):
|
||||
url = self.routable_page.reverse_subpage("external_view")
|
||||
|
||||
self.assertEqual(url, "external-no-arg/")
|
||||
|
||||
def test_get_index_route_view(self):
|
||||
with self.assertTemplateUsed("routablepagetests/routable_page_test.html"):
|
||||
response = self.client.get(self.routable_page.url)
|
||||
context = response.context_data
|
||||
self.assertEqual(
|
||||
(context["page"], context["self"], context.get("foo")),
|
||||
(self.routable_page, self.routable_page, None),
|
||||
)
|
||||
self.assertEqual(
|
||||
context["request"].routable_resolver_match.url_name, "index_route"
|
||||
)
|
||||
|
||||
def test_get_render_method_route_view(self):
|
||||
with self.assertTemplateUsed("routablepagetests/routable_page_test.html"):
|
||||
response = self.client.get(self.routable_page.url + "render-method-test/")
|
||||
context = response.context_data
|
||||
self.assertEqual(
|
||||
(context["page"], context["self"], context["foo"]),
|
||||
(self.routable_page, None, "bar"),
|
||||
)
|
||||
|
||||
def test_get_render_method_route_view_with_custom_template(self):
|
||||
with self.assertTemplateUsed(
|
||||
"routablepagetests/routable_page_test_alternate.html"
|
||||
):
|
||||
response = self.client.get(
|
||||
self.routable_page.url + "render-method-test-custom-template/"
|
||||
)
|
||||
context = response.context_data
|
||||
self.assertEqual(
|
||||
(context["page"], context["self"], context["foo"]),
|
||||
(self.routable_page, 1, "fighters"),
|
||||
)
|
||||
|
||||
def test_get_render_method_route_view_with_arg(self):
|
||||
response = self.client.get(
|
||||
self.routable_page.url + "render-method-with-arg/foo/"
|
||||
)
|
||||
resolver_match = response.context_data["request"].routable_resolver_match
|
||||
self.assertEqual(resolver_match.url_name, "render_method_test_with_arg")
|
||||
self.assertEqual(resolver_match.kwargs, {"slug": "foo"})
|
||||
|
||||
def test_get_routable_page_with_overridden_index_route(self):
|
||||
page = self.home_page.add_child(
|
||||
instance=RoutablePageWithOverriddenIndexRouteTest(
|
||||
title="Routable Page with overridden index", live=True
|
||||
)
|
||||
)
|
||||
response = self.client.get(page.url)
|
||||
self.assertContains(response, "OVERRIDDEN INDEX ROUTE")
|
||||
self.assertNotContains(response, "DEFAULT PAGE TEMPLATE")
|
||||
|
||||
def test_get_archive_by_year_view(self):
|
||||
response = self.client.get(self.routable_page.url + "archive/year/2014/")
|
||||
|
||||
self.assertContains(response, "ARCHIVE BY YEAR: 2014")
|
||||
|
||||
def test_earlier_view_takes_precedence(self):
|
||||
response = self.client.get(self.routable_page.url + "archive/year/1984/")
|
||||
|
||||
self.assertContains(response, "we were always at war with eastasia")
|
||||
|
||||
def test_get_archive_by_author_view(self):
|
||||
response = self.client.get(
|
||||
self.routable_page.url + "archive/author/joe-bloggs/"
|
||||
)
|
||||
|
||||
self.assertContains(response, "ARCHIVE BY AUTHOR: joe-bloggs")
|
||||
|
||||
def test_get_archive_by_title_view(self):
|
||||
response = self.client.get(self.routable_page.url + "archive/title/some-title/")
|
||||
|
||||
self.assertContains(response, "ARCHIVE BY TITLE: some-title")
|
||||
|
||||
def test_get_archive_by_category_view(self):
|
||||
response = self.client.get(
|
||||
self.routable_page.url + "archive/category/some-category/"
|
||||
)
|
||||
|
||||
self.assertContains(response, "ARCHIVE BY CATEGORY: some-category")
|
||||
|
||||
def test_get_external_view(self):
|
||||
response = self.client.get(self.routable_page.url + "external/joe-bloggs/")
|
||||
|
||||
self.assertContains(response, "EXTERNAL VIEW: joe-bloggs")
|
||||
|
||||
def test_get_external_view_other_route(self):
|
||||
response = self.client.get(self.routable_page.url + "external-no-arg/")
|
||||
|
||||
self.assertContains(response, "EXTERNAL VIEW: ARG NOT SET")
|
||||
|
||||
def test_routable_page_can_have_instance_bound_descriptors(self):
|
||||
# This descriptor pretends that it does not exist in the class, hence
|
||||
# it raises an AttributeError when class bound. This is, for instance,
|
||||
# the behaviour of django's FileFields.
|
||||
class InstanceDescriptor:
|
||||
def __get__(self, instance, cls=None):
|
||||
if instance is None:
|
||||
raise AttributeError
|
||||
return "value"
|
||||
|
||||
def __set__(self, instance, value):
|
||||
raise AttributeError
|
||||
|
||||
try:
|
||||
RoutablePageTest.descriptor = InstanceDescriptor()
|
||||
RoutablePageTest.get_subpage_urls()
|
||||
finally:
|
||||
del RoutablePageTest.descriptor
|
||||
|
||||
def test_warning_path_with_regex(self):
|
||||
route = path(r"^foo/$", lambda request: None, name="path_with_regex")
|
||||
|
||||
warning = checks.Warning(
|
||||
"Your URL pattern path_with_regex has a route that contains '(?P<', begins with a '^', or ends with a '$'.",
|
||||
hint="Decorate your view with re_path if you want to use regexp.",
|
||||
obj=RoutablePageTest,
|
||||
id="wagtailroutablepage.W001",
|
||||
)
|
||||
with mock.patch.object(
|
||||
RoutablePageTest, "get_subpage_urls", return_value=[route]
|
||||
):
|
||||
self.assertEqual(RoutablePageTest.check(), [warning])
|
||||
|
||||
|
||||
class TestRoutablePageTemplateTag(TestCase):
|
||||
def setUp(self):
|
||||
self.home_page = Page.objects.get(id=2)
|
||||
self.routable_page = self.home_page.add_child(
|
||||
instance=RoutablePageTest(
|
||||
title="Routable Page",
|
||||
live=True,
|
||||
)
|
||||
)
|
||||
|
||||
self.rf = RequestFactory()
|
||||
self.request = self.rf.get(self.routable_page.url)
|
||||
self.context = {"request": self.request}
|
||||
|
||||
def test_templatetag_reverse_index_route(self):
|
||||
url = routablepageurl(self.context, self.routable_page, "index_route")
|
||||
self.assertEqual(url, "/%s/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_archive_by_year_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "archive_by_year", "2014"
|
||||
)
|
||||
|
||||
self.assertEqual(url, "/%s/archive/year/2014/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_archive_by_author_view(self):
|
||||
url = routablepageurl(
|
||||
self.context,
|
||||
self.routable_page,
|
||||
"archive_by_author",
|
||||
author_slug="joe-bloggs",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url, "/%s/archive/author/joe-bloggs/" % self.routable_page.slug
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_archive_by_title_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "archive_by_title", title="some-title"
|
||||
)
|
||||
|
||||
self.assertEqual(url, "/%s/archive/title/some-title/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_archive_by_category_view(self):
|
||||
url = routablepageurl(
|
||||
self.context,
|
||||
self.routable_page,
|
||||
"archive_by_category",
|
||||
category_slug="some-category",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url, "/%s/archive/category/some-category/" % self.routable_page.slug
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_external_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "external_view", "joe-bloggs"
|
||||
)
|
||||
|
||||
self.assertEqual(url, "/%s/external/joe-bloggs/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_external_view_without_append_slash(self):
|
||||
with mock.patch("wagtail.models.WAGTAIL_APPEND_SLASH", False):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "external_view", "joe-bloggs"
|
||||
)
|
||||
expected = "/" + self.routable_page.slug + "/" + "external/joe-bloggs/"
|
||||
|
||||
self.assertEqual(url, expected)
|
||||
|
||||
|
||||
@override_settings(ALLOWED_HOSTS=["testserver", "localhost", "development.local"])
|
||||
class TestRoutablePageTemplateTagForSecondSiteAtSameRoot(TestCase):
|
||||
"""
|
||||
When multiple sites exist on the same root page, relative URLs within that subtree should
|
||||
omit the domain, in line with #4390
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
default_site = Site.objects.get(is_default_site=True)
|
||||
second_site = Site.objects.create( # add another site with the same root page
|
||||
hostname="development.local",
|
||||
port=default_site.port,
|
||||
root_page_id=default_site.root_page_id,
|
||||
)
|
||||
|
||||
self.home_page = Page.objects.get(id=2)
|
||||
self.routable_page = self.home_page.add_child(
|
||||
instance=RoutablePageTest(
|
||||
title="Routable Page",
|
||||
live=True,
|
||||
)
|
||||
)
|
||||
|
||||
self.rf = RequestFactory()
|
||||
self.request = self.rf.get(self.routable_page.url)
|
||||
self.context = {"request": self.request}
|
||||
self.request.META["HTTP_HOST"] = second_site.hostname
|
||||
self.request.META["SERVER_PORT"] = second_site.port
|
||||
|
||||
def test_templatetag_reverse_index_route(self):
|
||||
url = routablepageurl(self.context, self.routable_page, "index_route")
|
||||
self.assertEqual(url, "/%s/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_archive_by_year_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "archive_by_year", "2014"
|
||||
)
|
||||
|
||||
self.assertEqual(url, "/%s/archive/year/2014/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_archive_by_author_view(self):
|
||||
url = routablepageurl(
|
||||
self.context,
|
||||
self.routable_page,
|
||||
"archive_by_author",
|
||||
author_slug="joe-bloggs",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url, "/%s/archive/author/joe-bloggs/" % self.routable_page.slug
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_archive_by_title_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "archive_by_title", title="some-title"
|
||||
)
|
||||
|
||||
self.assertEqual(url, "/%s/archive/title/some-title/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_archive_by_category_view(self):
|
||||
url = routablepageurl(
|
||||
self.context,
|
||||
self.routable_page,
|
||||
"archive_by_category",
|
||||
category_slug="some-category",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url, "/%s/archive/category/some-category/" % self.routable_page.slug
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_external_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "external_view", "joe-bloggs"
|
||||
)
|
||||
|
||||
self.assertEqual(url, "/%s/external/joe-bloggs/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_external_view_without_append_slash(self):
|
||||
with mock.patch("wagtail.models.WAGTAIL_APPEND_SLASH", False):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "external_view", "joe-bloggs"
|
||||
)
|
||||
expected = "/" + self.routable_page.slug + "/" + "external/joe-bloggs/"
|
||||
|
||||
self.assertEqual(url, expected)
|
||||
|
||||
|
||||
@override_settings(ALLOWED_HOSTS=["testserver", "localhost", "events.local"])
|
||||
class TestRoutablePageTemplateTagForSecondSiteAtDifferentRoot(TestCase):
|
||||
"""
|
||||
When multiple sites exist, relative URLs between such sites should include the domain portion
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.home_page = Page.objects.get(id=2)
|
||||
|
||||
events_page = self.home_page.add_child(instance=Page(title="Events", live=True))
|
||||
|
||||
second_site = Site.objects.create(
|
||||
hostname="events.local",
|
||||
port=80,
|
||||
root_page=events_page,
|
||||
)
|
||||
|
||||
self.routable_page = self.home_page.add_child(
|
||||
instance=RoutablePageTest(
|
||||
title="Routable Page",
|
||||
live=True,
|
||||
)
|
||||
)
|
||||
|
||||
self.rf = RequestFactory()
|
||||
self.request = self.rf.get(self.routable_page.url)
|
||||
self.context = {"request": self.request}
|
||||
|
||||
self.request.META["HTTP_HOST"] = second_site.hostname
|
||||
self.request.META["SERVER_PORT"] = second_site.port
|
||||
|
||||
def test_templatetag_reverse_index_route(self):
|
||||
url = routablepageurl(self.context, self.routable_page, "index_route")
|
||||
self.assertEqual(url, "http://localhost/%s/" % self.routable_page.slug)
|
||||
|
||||
def test_templatetag_reverse_archive_by_year_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "archive_by_year", "2014"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url, "http://localhost/%s/archive/year/2014/" % self.routable_page.slug
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_archive_by_author_view(self):
|
||||
url = routablepageurl(
|
||||
self.context,
|
||||
self.routable_page,
|
||||
"archive_by_author",
|
||||
author_slug="joe-bloggs",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url,
|
||||
"http://localhost/%s/archive/author/joe-bloggs/" % self.routable_page.slug,
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_archive_by_title_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "archive_by_title", title="some-title"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url,
|
||||
"http://localhost/%s/archive/title/some-title/" % self.routable_page.slug,
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_archive_by_category_view(self):
|
||||
url = routablepageurl(
|
||||
self.context,
|
||||
self.routable_page,
|
||||
"archive_by_category",
|
||||
category_slug="some-category",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url,
|
||||
"http://localhost/%s/archive/category/some-category/"
|
||||
% self.routable_page.slug,
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_external_view(self):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "external_view", "joe-bloggs"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
url, "http://localhost/%s/external/joe-bloggs/" % self.routable_page.slug
|
||||
)
|
||||
|
||||
def test_templatetag_reverse_external_view_without_append_slash(self):
|
||||
with mock.patch("wagtail.models.WAGTAIL_APPEND_SLASH", False):
|
||||
url = routablepageurl(
|
||||
self.context, self.routable_page, "external_view", "joe-bloggs"
|
||||
)
|
||||
expected = (
|
||||
"http://localhost/"
|
||||
+ self.routable_page.slug
|
||||
+ "/"
|
||||
+ "external/joe-bloggs/"
|
||||
)
|
||||
|
||||
self.assertEqual(url, expected)
|
||||
Reference in New Issue
Block a user