8

How do I go about redirecting all requests for domain.com/... to www.domain.com/... with a 301 in a django site?

Obviously this can't be done in urls.py because you only get the path part of the URL in there.

I can't use mod rewrite in .htaccess, because .htaccess files do nothing under Django (I think).

I'm guessing something in middleware or apache conf?

I'm running Django on a Linux server with Plesk, using mod WSGI

maciek
  • 3,198
  • 2
  • 26
  • 33
Jake
  • 12,713
  • 18
  • 66
  • 96

4 Answers4

18

The WebFaction discussion someone pointed out is correct as far as the configuration, you just have to apply it yourself rather than through a control panel.

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule (.*) http://www.example.com/$1 [R=301,L]

Put in .htaccess file, or in main Apache configuration in appropriate context. If inside of a VirtualHost in main Apache configuration, your would have ServerName be www.example.com and ServerAlias be example.com to ensure that virtual host handled both requests.

If you don't have access to any Apache configuration, if need be, it can be done using a WSGI wrapper around the Django WSGI application entry point. Something like:

import django.core.handlers.wsgi
_application = django.core.handlers.wsgi.WSGIHandler()

def application(environ, start_response):
  if environ['HTTP_HOST'] != 'www.example.com':
    start_response('301 Redirect', [('Location', 'http://www.example.com/'),])
    return []
  return _application(environ, start_response)

Fixing this up to include the URL within the site and dealing with https is left as an exercise for the reader. :-)

Graham Dumpleton
  • 57,726
  • 6
  • 119
  • 134
  • That is a pretty slick little WSGI snippet. Definitely more elegant than the thing I linked. – jathanism Feb 18 '10 at 03:09
  • 1
    I have cheated a bit though. I have assumed 'http' only and haven't bothered with reconstructing the full URL and left that up to reader. Wanted to show the concept more than anything. The Django middleware is more correct. Overall though, mod_rewrite should simply be used. – Graham Dumpleton Feb 18 '10 at 03:13
  • 1
    Using Apache/Lighttpd/nginx configuration is more efficient than using django for this work. – jujule Feb 18 '10 at 09:35
  • Why shouldn't we use rather Apache `Redirect`? http://stackoverflow.com/a/1100363/1161025 – maciek Dec 04 '15 at 10:20
  • Redirect would be no good in case where example.com and www.example.com are actually handled within the same VirtualHost through use of ServerName and ServerAlias. Redirect would only be of use where you had separate VirtualHost for example.com and www.example.com. – Graham Dumpleton Dec 05 '15 at 10:33
15

The PREPEND_WWW setting does just that.

Luper Rouch
  • 9,304
  • 7
  • 42
  • 56
  • 4
    This is useful, but it's worth noting that it's completely indiscriminate... it will always add a www if there isn't one, so for a site that's also accessible from subdomains that shouldn't start with www, something like Graham's suggestions becomes necessary. – kungphu Apr 09 '13 at 22:34
4

There is a lightweight way to do that involving VirtualHosts and mod_alias Redirect directive. You can define two VirtualHosts, one holding the redirect and another holding the site configuration:

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / http://www.example.com/
</VirtualHost>

<VirtualHost *:80>
    ServerName www.example.com
    # real site configuration
</VirtualHost>

And that will do the job.

maciek
  • 3,198
  • 2
  • 26
  • 33
1

This also can be done with a middleware.

Some examples:

This is a better version of snippet-510:

class UrlRedirectMiddleware(object):
    """
    This middleware lets you match a specific url and redirect the request to a
    new url. You keep a tuple of (regex pattern, redirect) tuples on your site
    settings, example:

    URL_REDIRECTS = (
        (r'(https?)://(www\.)?sample\.com/(.*)$', r'\1://example.com/\3'),
    )
    """
    def process_request(self, request):
        full_url = request.build_absolute_uri()
        for url_pattern, redirect in settings.URL_REDIRECTS:
            match = re.match(url_pattern, full_url)
            if match:
                return HttpResponsePermanentRedirect(match.expand(redirect))
Taha Jahangir
  • 4,774
  • 2
  • 42
  • 49