Skip to content

Instantly share code, notes, and snippets.

@kaedroho
Last active September 21, 2019 01:20
Show Gist options
  • Save kaedroho/10296244 to your computer and use it in GitHub Desktop.
Save kaedroho/10296244 to your computer and use it in GitHub Desktop.
from django.http import Http404
from django.core.urlresolvers import RegexURLResolver
from django.conf.urls import url
from wagtail.wagtailcore.models import Page
class SuperPage(Page):
"""
This class extends Page by adding methods to allow urlconfs to be embedded inside pages
"""
def get_subpage_urls(self):
"""
Override this method to add your own subpage urls
"""
return [
url('^$', self.serve, name='main'),
]
def reverse_subpage(self, name, *args, **kwargs):
"""
This method does the same job as Djangos' built in "urlresolvers.reverse()" function for subpage urlconfs.
"""
resolver = RegexURLResolver(r'^', self.get_subpage_urls())
return self.url + resolver.reverse(name, *args, **kwargs)
def resolve_subpage(self, path):
"""
This finds a view method/function from a URL path.
"""
resolver = RegexURLResolver(r'^', self.get_subpage_urls())
return resolver.resolve(path)
def route(self, request, path_components):
"""
This hooks the subpage urls into Wagtails routing.
"""
if self.live:
try:
path = '/'.join(path_components)
if path:
path += '/'
view, args, kwargs = self.resolve_subpage(path)
return view(request, *args, **kwargs)
except Http404:
pass
return super(SuperPage, self).route(request, path_components)
@jeffrey-hearn
Copy link

I did a super-rough update of this to use the new RouteResult class. I don't know how hacky the override of serve() is or if it makes sense as an abstract class, but feel free to use what I've added if you wanted to try again to put this into wagtail.contrib. ¯_(ツ)_/¯

from django.db import models
from django.http import Http404
from django.core.urlresolvers import RegexURLResolver
from django.conf.urls import url

from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.url_routing import RouteResult


class SuperPage(models.Model):
    """
    This class extends Page by adding methods to allow urlconfs to be embedded inside pages
    """
    class Meta:
        abstract = True


    def get_subpage_urls(self):
        """
        Override this method to add your own subpage urls
        """
        return [
            url('^$', self.serve, name='main'),
        ]

    def reverse_subpage(self, name, *args, **kwargs):
        """
        This method does the same job as Djangos' built in "urlresolvers.reverse()" function for subpage urlconfs.
        """
        resolver = RegexURLResolver(r'^', self.get_subpage_urls())
        return self.url + resolver.reverse(name, *args, **kwargs)

    def resolve_subpage(self, path):
        """
        This finds a view method/function from a URL path.
        """
        resolver = RegexURLResolver(r'^', self.get_subpage_urls())
        return resolver.resolve(path)

    def route(self, request, path_components):
        """
        This hooks the subpage urls into Wagtails routing.
        """
        if self.live:
            try:
                path = '/'.join(path_components)
                if path:
                    path += '/'
                view, args, kwargs = self.resolve_subpage(path)
                return RouteResult(self, kwargs=dict(
                    sp_serve=True,
                    sp_fn=view,
                    sp_args=args,
                    sp_kwargs=kwargs
                    ))
            except Http404:
                pass

        return super(SuperPage, self).route(request, path_components)

    def serve(self, request, *args, **kwargs):

        if 'sp_serve' in kwargs and kwargs['sp_serve']:
            return kwargs['sp_fn']( request, kwargs['sp_args'], kwargs['sp_kwargs'] )
        return super(SuperPage, self).serve(request, *args, **kwargs)

With this consuming it:

class CustomPage(SuperPage, Page)
    ...

    def get_subpage_urls(self):
        return [
            url(r'^$', self.serve, name='main'),
            url(r'^download/$', self.download, name='download_request'),
        ]

    def download_link(self):
        return self.reverse_subpage('download_request')

    def download(self, request, *args, **kwargs):
        ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment