Added RoutablePage

This commit is contained in:
Karl Hobley 2014-05-20 14:33:14 +01:00
parent bbbc83c56e
commit 023579dc6b
5 changed files with 174 additions and 0 deletions

View file

@ -0,0 +1,66 @@
from six import string_types
from django.http import Http404
from django.core.urlresolvers import get_resolver
from django.core.exceptions import ImproperlyConfigured
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.url_routing import RouteResult
class RoutablePage(Page):
"""
This class extends Page by adding methods to allow urlconfs to be embedded inside pages
"""
subpage_urls = None
def reverse_subpage(self, name, args=None, kwargs=None):
"""
This method does the same job as Djangos' built in "urlresolvers.reverse()" function for subpage urlconfs.
"""
args = args or []
kwargs = kwargs or {}
if self.subpage_urls is None:
raise ImproperlyConfigured("You must set 'subpage_urls' on " + type(self).__name__)
resolver = get_resolver(self.subpage_urls)
return resolver.reverse(name, *args, **kwargs)
def resolve_subpage(self, path):
"""
This finds a view method/function from a URL path.
"""
if self.subpage_urls is None:
raise ImproperlyConfigured("You must set 'subpage_urls' on " + type(self).__name__)
resolver = get_resolver(self.subpage_urls)
view, args, kwargs = resolver.resolve(path)
# If view is a string, find it as an attribute of self
if isinstance(view, string_types):
view = getattr(self, view)
return view, args, kwargs
def route(self, request, path_components):
"""
This hooks the subpage urls into Wagtails routing.
"""
if self.live:
try:
path = '/'
if path_components:
path += '/'.join(path_components) + '/'
view, args, kwargs = self.resolve_subpage(path)
return RouteResult(self, view=view, args=args, kwargs=kwargs)
except Http404:
pass
return super(RoutablePage, self).route(request, path_components)
is_abstract = True
class Meta:
abstract = True

View file

@ -0,0 +1,82 @@
from django.test import TestCase
from wagtail.wagtailcore.models import Page
from wagtail.tests.models import RoutablePageTest, routable_page_external_view
class TestRoutablePage(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",
slug='routable-page',
live=True,
))
def test_resolve_serve_view(self):
view, args, kwargs = self.routable_page.resolve_subpage('/')
self.assertEqual(view, self.routable_page.serve)
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_external_view(self):
view, args, kwargs = self.routable_page.resolve_subpage('/external/joe-bloggs/')
self.assertEqual(view, routable_page_external_view)
self.assertEqual(args, ('joe-bloggs', ))
self.assertEqual(kwargs, {})
def test_reverse_serve_view(self):
url = self.routable_page.reverse_subpage('main')
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_external_view(self):
url = self.routable_page.reverse_subpage('external_view', args=('joe-bloggs', ))
self.assertEqual(url, 'external/joe-bloggs/')
def test_get_serve_view(self):
response = self.client.get(self.routable_page.url)
self.assertContains(response, "SERVE VIEW")
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_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_external_view(self):
response = self.client.get(self.routable_page.url + 'external/joe-bloggs/')
self.assertContains(response, "EXTERNAL VIEW: joe-bloggs")

View file

@ -1,6 +1,8 @@
from django.db import models
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.utils.encoding import python_2_unicode_compatible
from django.conf.urls import url
from django.http import HttpResponse
from modelcluster.fields import ParentalKey
@ -12,6 +14,7 @@ from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel
from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField
from wagtail.wagtailsnippets.models import register_snippet
from wagtail.wagtailsearch import indexed
from wagtail.contrib.wagtailroutablepage.models import RoutablePage
EVENT_AUDIENCE_CHOICES = (
@ -383,9 +386,31 @@ class SearchTestOldConfig(models.Model, indexed.Indexed):
},
}
class SearchTestOldConfigList(models.Model, indexed.Indexed):
"""
This tests that the Indexed class can correctly handle models that
use the old "indexed_fields" configuration format using a list.
"""
indexed_fields = ['title', 'content']
def routable_page_external_view(request, arg):
return HttpResponse("EXTERNAL VIEW: " + arg)
class RoutablePageTest(RoutablePage):
subpage_urls = (
url(r'^$', 'serve', name='main'),
url(r'^archive/year/(\d+)/$', 'archive_by_year', name='archive_by_year'),
url(r'^archive/author/(?P<author_slug>.+)/$', 'archive_by_author', name='archive_by_author'),
url(r'^external/(.+)/$', routable_page_external_view, name='external_view')
)
def archive_by_year(self, request, year):
return HttpResponse("ARCHIVE BY YEAR: " + str(year))
def archive_by_author(self, request, author_slug):
return HttpResponse("ARCHIVE BY AUTHOR: " + author_slug)
def serve(self, request):
return HttpResponse("SERVE VIEW")

View file

@ -72,6 +72,7 @@ INSTALLED_APPS = [
'wagtail.wagtailforms',
'wagtail.contrib.wagtailstyleguide',
'wagtail.contrib.wagtailsitemaps',
'wagtail.contrib.wagtailroutablepage',
'wagtail.tests',
]