Append OR remove slash in Django

2013-12-07

A frustration of mine is that while django provides the very useful APPEND_SLASH setting, it doesn't have a complementary REMOVE_SLASH setting, for those who prefer non-slashed urls.

Further, there are legitimate reasons to have trailing slashes on some urls, but not on others, so I wrote this short middleware to deal with the situation. It works just like APPEND_SLASH, and also works in reverse — e.g. it will remove the slash if a slash-appended url won't resolve, but its non-slashed counterpart will.

Usage

Download the code below and add slash_middleware.AppendOrRemoveSlashMiddleware to your MIDDLEWARE setting - somewhere near the start is best, usually right after CommonMiddleware. You also probably want to set APPEND_SLASH = False, since it will be redundant.

Potential issues

If you have an included urlconf followed by a catch-all without a trailing slash, the slash-append will not work - this issue is inherent with django, but can be solved by using a trailing slash on all urls, which is why we have APPEND_SLASH but no REMOVE_SLASH. For example:

urlpatterns = [
    url(r'^myurl/', include('myapp.urls')),
    url(r'^([\w\-]+)$', views.myview),
]

A request to /myurl will be resolved by the second url and therefore not be caught by the middleware, which detects 404s at the url level but not those raised by a view. The result will generally be a 404 when a redirect to /myurl/ might be expected. To work around this an explicit redirect is required, e.g

urlpatterns = [
    (r'^myurl$', RedirectView.as_view(url='/myurl/')),
    url(r'^myurl/', include('myapp.urls')),
    url(r'^([\w\-]+)$', views.myview),
]

Get the code

https://gist.github.com/gregplaysguitar/1440567