1

I am using the catch all pattern for flatpages in Django, like this:-

urlpatterns = [
    path('somepath/', include('project.somepathapp.urls')),
    path('anotherpath/', include('project.anotherpathapp.urls')),
    etc.
]

urlpatterns += [
    path('<path:url>/', views.flatpage),
]

In my template, I use:-

<a href="/about-us/">About Us</a>

to get to the About flatpage. But the URL pattern strips off the final slash and passes the flatpage view the URL /about-us (as opposed to /about-us/). The flatpage view then spots that the URL doesn't end in a slash, adds it back in, finds the page and redirects to that URL but adds an extra slash so that the URL is now /about-us//

If I remove the final slash from the catch all pattern, any URL from the main paths (somepath/ and anotherpath/) without the final slash is matched by the catch all pattern before the APPEND_SLASH is used and, since there is no page with that URL, the user gets a 404. So a URL like /somepath/ will work but /somepath won't.

What have I done wrong? It seems like a catch-22 to me. I can't use the middleware option because that doesn't always get passed through other middleware views so I'm stuck.

Any ideas?

bodger
  • 1,112
  • 6
  • 24
  • The trailing slash was added to the example in the docs recently for [ticket 31330](https://code.djangoproject.com/ticket/31330). If that hasn't fixed the problem (or it's created another one) then it might be worth adding a comment to the ticket. – Alasdair Mar 20 '20 at 14:56
  • You could also try the `url()` version of the catch all pattern from the [Django 1.11 docs](https://docs.djangoproject.com/en/1.11/ref/contrib/flatpages/). Update to `re_path()` if you prefer. – Alasdair Mar 20 '20 at 14:59
  • 1
    Thanks @Alasdair. I think it's created another one. And interestingly, the code in django.contrib.flatpages.urls doesn't have it, so if you include it from there, it doesn't have it. For some reason, it didn't occur to me to use re_path. It seems to work if I use re_path('^(?P.+/)$', views.flatpage) so, for the time being, I'll go that way. Much appreciated. – bodger Mar 20 '20 at 15:05
  • Glad that worked. BTW, I saw your comment on the Django bugtracker, I think you are missing `//` at the end of *the user will be redirected to '/someurl'.* – Alasdair Mar 20 '20 at 16:19
  • 1
    Good spot - it was in the markup - but it was interpreted as blank for some reason. I've forced it now - doesn't look great but I don't know how to do it "properly" and it gets the message across. Thanks. – bodger Mar 21 '20 at 10:37

0 Answers0