Most web developers know it’s possible to serve one site on several domains or subdomains, using eg. the ServerAlias Apache directive. Sometimes this behaviour is not wanted: you want your main domain to be “foo.tld”, although “www.foo.tld” should work too, and maybe even some completely different domains.
This way it’s possible to have permalinks, and you won’t get bad points from search engine spiders who don’t like the same content to be available on several URIs.
In Django there’s the PREPEND_WWW setting, which will force all requests to be redirected to www.foo.bar when coming in on foo.bar, etc. This functionality is rather limited though. As I wanted to be able to have one unique main domain in my new application, I wrote a middleware which accomplishes this in a very generic way, using the django.contrib.sites framework. You need to add this middleware before all others in your settings file, even before the CommonMiddleware.
Here’s the code:
from django.contrib.sites.models import Site from django.http import HttpResponsePermanentRedirect from django.core.urlresolvers import resolve from django.core import urlresolvers from django.utils.http import urlquote class DomainRedirectMiddleware(object): def process_request(self, request): host = request.get_host() site = Site.objects.get_current() if host == site.domain: return None # Only redirect if the request is a valid path try: # One issue here: won't work when using django.contrib.flatpages # TODO: Make this work with flatpages resolve(request.path) except urlresolvers.Resolver404: return None new_uri = '%s://%s%s%s' % ( request.is_secure() and 'https' or 'http', site.domain, urlquote(request.path), (request.method == 'GET' and len(request.GET) > 0) and '?%s' % request.GET.urlencode() or '' ) return HttpResponsePermanentRedirect(new_uri)
Make sure you got the sites framework set up correctly when using this! As noted in the code, this doesn’t work with the Flatpages framework yet, this is TODO.
Why not use virtual hosts with rewriterules?
If you’re using apache anyway, then this is the most elegant solution IMHO.
You want every request to go to http://www.somesite.net, but used to have http://www.oldsite.org, then set up a virtual host on http://www.oldsite.org containing nothing but a rewriterule:
RewriteEngine On
RewriteRule ^(.*)$ http://www.somesite.net/$1 [R=permanent]
That way, client software even gets a 301 signal, giving the browser the possibility to automatically update your bookmarks.
Vincent: my solution also uses a HTTP 301 (a HttpResponsePermanentRedirect also translates to a HTTP 301 reply). One of the main benefits is it doesn’t force you to use multiple vhosts, which is not always possible in shared hosting environments.
By the way, your solution could be simplified by using something like
in your Apache configuration, instead of pulling in mod_rewrite
I just used your solution, it works flawlessly. Thanks !
I know I could have used apache mod_rewrite instead, but I felt more secure with your solution, since I understand django/python much better.
The forum is a bihrtger place thanks to your posts. Thanks!
Does the last solution of Nicolas keep the whole URL?
For example if I’m poiting to http://website.org/cars/view/1/, I want to redirect to http://www.website.org/cars/view/1/, right?
Thanks a lot!
If you’re running Django on a non-default port, you might want to add the port number to the newly constructed URI:
new_uri = ‘%s://%s%s%s%s’ % (
request.is_secure() and ‘https’ or ‘http’,
site.domain,
(“:” + request.META["SERVER_PORT"]) if request.META["SERVER_PORT"]!=80 else “”,
urlquote(request.path),
(request.method == ‘GET’ and len(request.GET) > 0) and ‘?%s’ % request.GET.urlencode() or ”
)
oh and say host = request.get_host().split(‘:’)[0] above there