eg. example.com/page and example.com/page/
This affects some web frameworks, such as Django, as the regular expression for routing these URLs will be defined for only one of these cases. By convention Django will add a trailing slash, if a non trailing slash url is typed into the browser.
I prefer to not have a trailing slash as it is one less character to type in. I should note that some sites, like stackoverflow.com or twitter.com does not give a crap either way.
We can add this feature to Django by creating a custom middleware class that intercepts the request.path and rewrites it to the non trailing slash url.
What is middleware?
Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.
Or in layman's terms, it processes values/urls before it is sent to Django's views. You can find Django's middleware that redirects to the trailing slash url in:
django/middleware/common.py
Which was added to your project in
settings.py
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware',
How to get Django to redirect trailing slashes to the non trailing slash url if it exists.
Step 1:
Add this line in settings.py
APPEND_SLASH = False
Step 2:
Create these paths and files
./common/
./common/__init__.py
./common/redirect.py
Step 3: Add the class to the MIDDLEWARE definition
MIDDLEWARE_CLASSES = (
'common.redirect.RedirectTrailingSlashMiddleware',
'django.middleware.common.CommonMiddleware',
# It must be the first class as we want to catch it before django does.
Step 4: Add this code to redirect.py
For /admin urls, I have kept the trailing slash as I don't want to break Django's admin methods
from django.conf import settings from django.core import urlresolvers from django import http ''' Based on django/middleware/common.py Django convention is to add trailing slashes to most urls This method does the opposite and redirects trailing slashes to the no trailing slash url if it exists ''' class RedirectTrailingSlashMiddleware(object): def process_request(self, request): if settings.APPEND_SLASH: return if '/admin' in request.path: settings.APPEND_SLASH = True return new_url = old_url = request.path if (old_url.endswith('/')): urlconf = getattr(request, 'urlconf', None) if (not urlresolvers.is_valid_path(request.path_info, urlconf) and urlresolvers.is_valid_path(request.path_info[:-1], urlconf)): new_url = new_url[:-1] if settings.DEBUG and request.method == 'POST': raise RuntimeError(("" "You called this URL via POST, but the URL ends " "in a slash and you have APPEND_SLASH set. Django can't " "redirect to the non-slash URL while maintaining POST data. " "Change your form to point to %s (note no trailing " "slash), or set APPEND_SLASH=True in your Django " "settings.") % (new_url)) if new_url == old_url: # No redirects required. return return http.HttpResponsePermanentRedirect(new_url)
1 comment:
An old post but, several years after you posted it, this did just the trick for me today - thanks Bunwich!
Post a Comment