mirror of
https://github.com/wagtail/wagtail.git
synced 2024-11-29 09:33:54 +01:00
Take MRO into account when constructing RoutablePageMixin's list of routes
This ensures that routes can be overridden in subclasses, while still respecting the definition order within a class definition.
This commit is contained in:
parent
44a1c28481
commit
913607c939
@ -49,15 +49,23 @@ class RoutablePageMixin(object):
|
||||
@classmethod
|
||||
def get_subpage_urls(cls):
|
||||
routes = []
|
||||
for attr in dir(cls):
|
||||
val = getattr(cls, attr, None)
|
||||
if hasattr(val, '_routablepage_routes'):
|
||||
routes.extend(val._routablepage_routes)
|
||||
|
||||
return tuple([
|
||||
route[0]
|
||||
for route in reversed(sorted(routes, key=lambda route: route[1]))
|
||||
])
|
||||
# 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):
|
||||
|
@ -110,6 +110,11 @@ class TestRoutablePage(TestCase):
|
||||
|
||||
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/')
|
||||
|
||||
|
@ -10,6 +10,10 @@ def routable_page_external_view(request, arg="ARG NOT SET"):
|
||||
|
||||
|
||||
class RoutablePageTest(RoutablePage):
|
||||
@route(r'^archive/year/1984/$')
|
||||
def archive_for_1984(self, request):
|
||||
# check that routes are tested in order (and thus this takes precedence over archive_by_year)
|
||||
return HttpResponse("we were always at war with eastasia")
|
||||
|
||||
@route(r'^archive/year/(\d+)/$')
|
||||
def archive_by_year(self, request, year):
|
||||
|
Loading…
Reference in New Issue
Block a user