Well, after not finding what I needed, I came to the following solution.
I discarded the request.urlconf
mapping and went for rewriting request.path_info
.
I'm posting my solution here, in case someone runs into this problem.
First step, add the following middleware to your project:
class SubdomainMiddleware:
"""Subdomain for Django"""
def process_request(self, request):
domain_parts = request.get_host().lower().replace('www.', '').split('.example.com', 1)
if len(domain_parts) > 1 and domain_parts[0]:
subdomain = domain_parts[0]
else:
subdomain = None
if subdomain:
if request.path_info[-1] != '/':
request.path_info += '/'
request.path_info = '/%s%s' % (subdomain, request.path_info)
Next, add the following code that overrides the reverse
function:
from django.conf import settings
from django.core import urlresolvers
_reverse = urlresolvers.reverse
def reverse(*args, **kwargs):
# In case reversing a full url
if args[0].startswith('http'):
return args[0]
# In case reversing a url name
if '/' not in args[0]:
url = _reverse(*args, **kwargs)
else:
# In case reversing a url path
url = args[0]
parts = url.strip('/').split('/', 1)
subdomain = parts[0]
path = parts[1] if len(parts) > 1 else ''
protocol = 'http://' if settings.DEBUG else 'https://'
return '%s%s%s/%s' % (protocol, subdomain, '.example.com', path)
urlresolvers.reverse = reverse
I placed it in the same file the custom middleware sits.
That's it!
As far as I know and tested, everything works: reversing, redirecting, template {% url %} tags etc.
Note:
I made three assumptions in this code:
- The domain name is
example.com
. Change it as you need, place it in settings.py
, whatever suits you.
- The subdomain maps to a subfolder. E.g.
sub.example.com
will be converted to example.com/sub
.
- My site uses SSL anywhere. So I simply check for
settings.DEBUG
value in the custom reverse
function to see if it should use http
or https
.
Hope it helps.