djangourldjango-flatpages

Django flat pages with .html extension


I am trying to set up django flat pages that would be accessible via a url like /pages/page1.html instead of /pages/page1.

Followed the flatpages docs, and instead of the flatpages middleware used this code in the root urls.py (in the same folder with settings.py):

re_path('pages/.*\.html$', include('django.contrib.flatpages.urls')), 

But this results in a 404 error.

I tried specifying the extension as a non-capturing group:

re_path('pages/.*(?:\.html)$', include('django.contrib.flatpages.urls')),

but I'm still getting a 404.

What would be the correct way to have the .html suffix for flatpages?


Solution

  • You can't use include that way. The .* part of the match will simply be thrown away, and not passed to the flatpage view.

    But you can hook up your flatpages view directly, and capture the url part in a group.

    Since the flatpages app requires the url part to have both a leading and trailing slash (/foobar/), you must adapt the flatpage view function with a decorator that replaces the .html extension with a /.

    from functools import wraps
    import re
    from django.contrib.flatpages.views import flatpage
    
    def replace_dot_html_with_slash(f):
        """Decorator that adapt the flatpage view to accept .html urls"""
        @wraps(f)
        def wrapper(request, url):
            # pretend the url has a trailing slash instead of `.html`
            return f(request, re.sub(r'\.html$', '/', url))
        return wrapper
    
    adapted_flatpage = replace_dot_html_with_slash(flatpage)
    
    urlpatterns = [
       ...
       re_path(r'^pages/(.*)$', adapted_flatpage)
    ]
    

    Alternatively, you could simply write your own flatpage view. It doesn't do anything very complicated.

    There are more examples of how to configure flatpages routes in the docs. https://docs.djangoproject.com/en/2.0/ref/contrib/flatpages/#using-the-urlconf