diff --git a/wagtail/core/templatetags/wagtailcore_tags.py b/wagtail/core/templatetags/wagtailcore_tags.py
index 7f13ba27a7..6f2c7ad672 100644
--- a/wagtail/core/templatetags/wagtailcore_tags.py
+++ b/wagtail/core/templatetags/wagtailcore_tags.py
@@ -34,8 +34,25 @@ def pageurl(context, page):
@register.simple_tag(takes_context=True)
def slugurl(context, slug):
- """Returns the URL for the page that has the given slug."""
- page = Page.objects.filter(slug=slug).first()
+ """
+ Returns the URL for the page that has the given slug.
+
+ First tries to find a page on the current site. If that fails or a request
+ is not available in the context, then returns the URL for the first page
+ that matches the slug on any site.
+ """
+
+ try:
+ current_site = context['request'].site
+ except (KeyError, AttributeError):
+ # No site object found - allow the fallback below to take place.
+ page = None
+ else:
+ page = Page.objects.in_site(current_site).filter(slug=slug).first()
+
+ # If no page is found, fall back to searching the whole tree.
+ if page is None:
+ page = Page.objects.filter(slug=slug).first()
if page:
# call pageurl() instead of page.relative_url() here so we get the ``accepts_kwarg`` logic
diff --git a/wagtail/core/tests/tests.py b/wagtail/core/tests/tests.py
index ce8b001c37..e70eacb97c 100644
--- a/wagtail/core/tests/tests.py
+++ b/wagtail/core/tests/tests.py
@@ -5,7 +5,7 @@ from django.test import TestCase
from django.utils.safestring import SafeText
from wagtail.core.models import Page, Site
-from wagtail.core.templatetags.wagtailcore_tags import richtext
+from wagtail.core.templatetags.wagtailcore_tags import richtext, slugurl
from wagtail.core.utils import resolve_model_string
from wagtail.tests.testapp.models import SimplePage
@@ -43,27 +43,47 @@ class TestPageUrlTags(TestCase):
with self.assertRaisesRegex(ValueError, "pageurl tag expected a Page object, got None"):
tpl.render(template.Context({'page': None}))
- def test_slugurl_without_request_in_context(self):
- tpl = template.Template('''{% load wagtailcore_tags %}Events''')
-
- # no 'request' object in context
- result = tpl.render(template.Context({}))
- self.assertIn('Events', result)
-
- # 'request' object in context, but no 'site' attribute
- result = tpl.render(template.Context({'request': HttpRequest()}))
- self.assertIn('Events', result)
-
def test_bad_slugurl(self):
- tpl = template.Template('''{% load wagtailcore_tags %}Events''')
-
# no 'request' object in context
- result = tpl.render(template.Context({}))
- self.assertIn('Events', result)
+ result = slugurl(template.Context({}), 'bad-slug-doesnt-exist')
+ self.assertEqual(result, None)
# 'request' object in context, but no 'site' attribute
- result = tpl.render(template.Context({'request': HttpRequest()}))
- self.assertIn('Events', result)
+ result = slugurl(context=template.Context({'request': HttpRequest()}), slug='bad-slug-doesnt-exist')
+ self.assertEqual(result, None)
+
+ def test_slugurl_tag_returns_url_for_current_site(self):
+ home_page = Page.objects.get(url_path='/home/')
+ new_home_page = home_page.copy(update_attrs={'title': "New home page", 'slug': 'new-home'})
+ second_site = Site.objects.create(hostname='site2.example.com', root_page=new_home_page)
+ # Add a page to the new site that has a slug that is the same as one on
+ # the first site, but is in a different position in the treeself.
+ new_christmas_page = Page(title='Christmas', slug='christmas')
+ new_home_page.add_child(instance=new_christmas_page)
+ request = HttpRequest()
+ request.site = second_site
+ url = slugurl(context=template.Context({'request': request}), slug='christmas')
+ self.assertEqual(url, '/christmas/')
+
+ def test_slugurl_tag_returns_url_for_other_site(self):
+ home_page = Page.objects.get(url_path='/home/')
+ new_home_page = home_page.copy(update_attrs={'title': "New home page", 'slug': 'new-home'})
+ second_site = Site.objects.create(hostname='site2.example.com', root_page=new_home_page)
+ request = HttpRequest()
+ request.site = second_site
+ # There is no page with this slug on the current site, so this
+ # should return an absolute URL for the page on the first site.
+ url = slugurl(slug='christmas', context=template.Context({'request': request}))
+ self.assertEqual(url, 'http://localhost/events/christmas/')
+
+ def test_slugurl_without_request_in_context(self):
+ # no 'request' object in context
+ result = slugurl(template.Context({}), 'events')
+ self.assertEqual(result, '/events/')
+
+ # 'request' object in context, but no 'site' attribute
+ result = slugurl(template.Context({'request': HttpRequest()}), 'events')
+ self.assertEqual(result, '/events/')
class TestSiteRootPathsCache(TestCase):