Use resolve_url() instead of reverse() for pageurl fallbacks (#7002)

pull/7008/head
Andy Babic 2021-04-13 16:10:45 +01:00 zatwierdzone przez Matt Westcott
rodzic b1b69360a3
commit 9630967e0e
5 zmienionych plików z 47 dodań i 8 usunięć

Wyświetl plik

@ -18,6 +18,7 @@ Changelog
* `get_settings` template tag now supports specifying the variable name with `{% get_settings as var %}` (Samir Shah)
* Reinstate submitter's name on moderation notification email (Matt Westcott)
* Add a new switch input widget as an alternative to checkboxes (Karl Hobley)
* Allow `{% pageurl %}` fallback to be a direct URL or an object with a `get_absolute_url` method (Andy Babic)
* Fix: StreamField required status is now consistently handled by the `blank` keyword argument (Matt Westcott)
* Fix: Show 'required' asterisks for blocks inside required StreamFields (Matt Westcott)
* Fix: Make image chooser "Select format" fields translatable (Helen Chapman, Thibaud Colas)

Wyświetl plik

@ -35,6 +35,7 @@ Other features
* ``get_settings`` template tag now supports specifying the variable name with ``{% get_settings as var %}`` (Samir Shah)
* Reinstate submitter's name on moderation notification email (Matt Westcott)
* Add a new switch input widget as an alternative to checkboxes (Karl Hobley)
* Allow ``{% pageurl %}`` fallback to be a direct URL or an object with a ``get_absolute_url`` method (Andy Babic)
Bug fixes
~~~~~~~~~

Wyświetl plik

@ -174,7 +174,7 @@ Takes a Page object and returns a relative URL (``/foo/bar/``) if within the sam
<a href="{% pageurl page.get_parent %}">Back to index</a>
A ``fallback`` keyword argument can be provided - this should be a URL route name that takes no parameters, and will be used as a substitute URL when the passed page is ``None``.
A ``fallback`` keyword argument can be provided - this can be a URL string, a named URL route that can be resolved with no parameters, or an object with a ``get_absolute_url`` method, and will be used as a substitute URL when the passed page is ``None``.
.. code-block:: html+django

Wyświetl plik

@ -1,5 +1,5 @@
from django import template
from django.shortcuts import reverse
from django.shortcuts import resolve_url
from django.template.defaulttags import token_kwargs
from django.template.loader import render_to_string
from django.utils.encoding import force_str
@ -21,7 +21,7 @@ def pageurl(context, page, fallback=None):
If kwargs contains a fallback view name and page is None, the fallback view url will be returned.
"""
if page is None and fallback:
return reverse(fallback)
return resolve_url(fallback)
if not hasattr(page, 'relative_url'):
raise ValueError("pageurl tag expected a Page object, got %r" % page)

Wyświetl plik

@ -21,13 +21,50 @@ class TestPageUrlTags(TestCase):
self.assertContains(response,
'<a href="/events/christmas/">Christmas</a>')
def test_pageurl_fallback(self):
tpl = template.Template('''{% load wagtailcore_tags %}<a href="{% pageurl page fallback='fallback' %}">Fallback</a>''')
result = tpl.render(template.Context({'page': None}))
def test_pageurl_with_named_url_fallback(self):
tpl = template.Template(
"""{% load wagtailcore_tags %}<a href="{% pageurl page fallback='fallback' %}">Fallback</a>"""
)
result = tpl.render(template.Context({"page": None}))
self.assertIn('<a href="/fallback/">Fallback</a>', result)
def test_pageurl_fallback_without_valid_fallback(self):
tpl = template.Template('''{% load wagtailcore_tags %}<a href="{% pageurl page fallback='not-existing-endpoint' %}">Fallback</a>''')
def test_pageurl_with_get_absolute_url_object_fallback(self):
class ObjectWithURLMethod:
def get_absolute_url(self):
return "/object-specific-url/"
tpl = template.Template(
"""{% load wagtailcore_tags %}<a href="{% pageurl page fallback=object_with_url_method %}">Fallback</a>"""
)
result = tpl.render(
template.Context({"page": None, "object_with_url_method": ObjectWithURLMethod()})
)
self.assertIn('<a href="/object-specific-url/">Fallback</a>', result)
def test_pageurl_with_valid_url_string_fallback(self):
"""
`django.shortcuts.resolve_url` accepts strings containing '.' or '/' as they are.
"""
tpl = template.Template(
"""
{% load wagtailcore_tags %}
<a href="{% pageurl page fallback='.' %}">Same page fallback</a>
<a href="{% pageurl page fallback='/' %}">Homepage fallback</a>
<a href="{% pageurl page fallback='../' %}">Up one step fallback</a>
"""
)
result = tpl.render(template.Context({"page": None}))
self.assertIn('<a href=".">Same page fallback</a>', result)
self.assertIn('<a href="/">Homepage fallback</a>', result)
self.assertIn('<a href="../">Up one step fallback</a>', result)
def test_pageurl_with_invalid_url_string_fallback(self):
"""
Strings not containing '.' or '/', and not matching a named URL will error.
"""
tpl = template.Template(
"""{% load wagtailcore_tags %}<a href="{% pageurl page fallback='not-existing-endpoint' %}">Fallback</a>"""
)
with self.assertRaises(NoReverseMatch):
tpl.render(template.Context({'page': None}))