最近一直在用Django寫東西,感覺非常棒,開發效率非常高,系統本身也很靈活。但是這樣一個強大的框架也並非完美,目前,Django還不支持域名的處理,URL的路由並不考慮host信息,因此對於曬課廳這樣的項目,如果想使用二級域名作爲學校的區分,就顯得有些困難。
於是我們有必要想個辦法解決這個問題。一個比較方便的做法是,使用middleware對URL做一些修改,通過一點技巧來讓URL的路由「識別」二級域名。不難想到這樣處理:
假設我們有兩個二級域名需要放在一個Django項目裏,分別是:www.shaiketing.com和thu.shaiketing.com,那麼爲了使用URL的路由,我們需要讓路由系統知道我們訪問的是www和thu,而路由系統並不關心host信息,所以我們只要讓路由系統看到/www/和/thu/就好。因此,我們實際上是把這兩個URL變成了www.shaiketing.com/www/和thu.shaiketing.com/thu/,這樣路由系統就知道我們訪問的是什麼二級域名了。
具體怎麼做呢?寫一個middleware:
from django.http import HttpResponsePermanentRedirect
class SubdomainMiddleware(object):
def process_request(self, request):
domain_parts = request.get_host().split('.')
if len(domain_parts) == 3:
request.path_info = '/%s%s' % (domain_parts[0], request.path)
else:
return HttpResponsePermanentRedirect('http://www.shaiketing.com')
return None
通過這樣的middleware,我們就可以將二級域名附加到URL路由用到的request.path_info裏了。
然而,這樣做還會有點問題,reverse的時候並沒有host信息,所以我們還需要對reverse做一下處理:
from django.conf import settings
from django.core import urlresolvers
def reverse_subdomain(*args, **kwargs):
path_info = old_reverse(*args, **kwargs)
parts = path_info[1:].split('/', 1)
path_info = 'http://%s%s/%s' % (
parts[0], settings.SESSION_COOKIE_DOMAIN, parts[1])
return path_info
old_reverse = urlresolvers.reverse
urlresolvers.reverse = reverse_subdomain
一定要把這段代碼加在某個models.py裏,加在其他位置都不合適(可以想想爲什麼?)
現在這個問題應該比較完美的解決了。最後附上urls.py:
from django.conf.urls.defaults import patterns, include, url
urlpatterns = patterns('',
url(r'^www/', include('www.urls')),
url(r'^thu/', include('thu.urls')),
)