2013-10-15 20 views
4

我有一個Django應用程序,目前支持多種語言。我想添加子域支持,以便'de.mysite.com'用德語查詢文章,而'mysite.com'用英語查詢(默認語言)。將有大約20個子域指向相同的Django應用程序。如何捕獲Django URL模式中的子域名?

我有一個抽象模型,包含我的數據的所有字段和每種語言的派生模型。每一種語言都有它自己的數據庫表,就像這樣:

class ArticleBase(models.Model): 
    title = models.CharField(max_length=240, unique=True) 
    date_added = models.DateField(auto_now_add=True) 

    class Meta: 
     abstract = True 

# This is English, the default. 
class Article(ArticleBase): 
    pass 

class Article_de(ArticleBase): 
    pass 

我能得到這樣的文章(我這方面的工作有今天):

def article(request, title, language=None): 
    if language: 
     mod = get_model('app', 'Article_' + language) 
     items = mod.filter(title=title) 
    else: 
     items = Article.objects.filter(title=title) 

這是我當前的URL模式:

url(r'^article/(?P<title>[a-zA-Z_-]+)/$", 'app.views.article', name='article'), 

如何解析URL模式中的子域名前綴,以便將其傳遞到文章視圖中?或者我應該在處理視圖時從請求中獲取此信息?

回答

5

django中的URL無權訪問URL的域部分,因此這不是一個選項。 在每個視圖中手動執行操作是可行的,但不容易維護。

我認爲,一個自定義的中間件解決方案可能是更好的,你檢查請求頭中的中間件,然後加載相應的語言(或您更換接受語言頭,讓Django的做它的魔力)

localemiddleware可以使語言可用,然後您可以輕鬆使用該語言根據需要傳遞給模型/查詢。

另外,如果我可能會問:爲什麼要將每個條目存儲在單獨的表格/模型中?難道你不能只在模型中添加一個語言字段並將所有內容存儲在一張表中?因爲去製作20個左右的文章模型可能會比僅僅1個模型更難以維護。

UPDATE:

我周圍一點點發揮和所需的中間件很簡單(雖然我的測試是相當有限的):

class SubDomainLanguage(object): 
    def process_request(self, request): 
     try: 
      request.session['django_language'] = request.META['HTTP_HOST'].split('.')[0] 
     except KeyError: 
      pass 

是中間件,然後將設置更改爲包括以下內容:

MIDDLEWARE_CLASSES = (
    ... 
    'django.contrib.sessions.middleware.SessionMiddleware', 
    'subdomainmiddleware.SubDomainLanguage', 
    'django.middleware.locale.LocaleMiddleware', 
    ... 
) 

這樣您就可以利用正常的Django內置i18n支持。

在視圖的語言是隨後在request.LANGUAGE_CODE

+0

謝謝,這是一個很好的解決方案。我正在處理位於不同位置的幾臺服務器上的大量數據,並通過語言對其進行分區,從而使查詢時間縮短,並讓我將單獨的事情保存在單獨的服務器上,並通過DNS進行路由 - 目前爲en/es,一個用於de/fr/pt,另一個用於「其他語言」。 :) –

0

可用我有具有周期如1.2.3.mydomain.net子域的情況。我知道我的域名,並將其設置在我local_settings.py爲:

DOMAIN = 'EXAMPLE.net' 
TEST_SUBDOMAINS = ["127.0.0.1", "localhost", "testserver"] 

我再查,我不如果用於測試目的做任何事情。 之後,我讓我的子域如下:

if (DOMAIN in TEST_SUBDOMAINS): 
    return HttpResponse("test only") 
subdomain = request.META['HTTP_HOST'].replace((DOMAIN), "")[:-1] 
# -1 is to remove the trailing "." from the subdomain 
if subdomain and subdomain != "www" : 
# whatever you need...