6๐
The RoutablePageMixin is the current (v2.0+) way to accomplish this.
Add the module to your installed apps:
INSTALLED_APPS = [
...
"wagtail.contrib.routable_page",
]
Inherit from both wagtail.contrib.routable_page.models.RoutablePageMixin
and wagtail.core.models.Page
, then define some view methods and decorate them with the wagtail.contrib.routable_page.models.route
decorator:
from wagtail.core.models import Page
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
class EventPage(RoutablePageMixin, Page):
...
@route(r'^$') # will override the default Page serving mechanism
def current_events(self, request):
"""
View function for the current events page
"""
...
@route(r'^past/$')
def past_events(self, request):
"""
View function for the past events page
"""
...
# Multiple routes!
@route(r'^year/(\d+)/$')
@route(r'^year/current/$')
def events_for_year(self, request, year=None):
"""
View function for the events for year page
"""
...
2๐
New in Wagtail v0.5 is a mechanism that directly addresses this sort of thing:
Embedding URL configuration in Pages or RoutablePage in v1.3.1
(the docs even have an Blog example!)
- [Django]-Show models.ManyToManyField as inline, with the same form as models.ForeignKey inline
- [Django]-Does Django ModelForm set unspecified fields to empty?
- [Django]-Django-extensions: Run a script using runscript which is inside a folder within scripts
- [Django]-Force re-collectstatic with django static?
- [Django]-Decorating a sitemap view in Django
2๐
I was looking into migrating my blog to a wagtail version and wanted to support my previous url schema and had to solve this exact problem. Luckily I just found a solution and want to share it, hopefully this will be helpful for someone else in the future.
The solution is a 2 Step process.
- change the url of a blog page to contain the date as well.
class Blog(Page):
created = models.DateTimeField(auto_now_add=True)
def get_url_parts(self, request=None):
super_response = super().get_url_parts(request)
# handle the cases of the original implementation
if super_response is None:
return None
(site_id, root_url, page_path) = super_response
if page_path == None:
return super_response
# In the happy case, add the date fields
# split prefix and slug to support blogs that are nested
prefix, slug, _ = page_path.rsplit("/", 2)
return (
site_id,
root_url,
f"{prefix}/{self.created.year}/{self.created.month}/{self.created.day}/{slug}/",
)
- And now we need to make those posts also route-able.
class BlogIndexPage(RoutablePageMixin, Page):
...
def route(self, request, path_components):
if len(path_components) >= 4:
year, month, day, slug, *rest = path_components
try:
subpage = self.get_children().get(slug=slug)
return subpage.specific.route(request, rest)
except Page.DoesNotExist:
...
return super().route(request, path_components)
This solution ignores the date and just use the slug to locate a blog post as the original solution. This should also work when you donโt use the RoutablePageMixin
.
Hope this is still helpful for someone.
- [Django]-Django Forms for generic relationships. How to include them?
- [Django]-Django โ how to restrict DeleteView to object owner
- [Django]-Django saving form strings in database with extra characters (u'string')