如何捕获Django URL模式中的子域?

时间:2013-10-15 15:42:31

标签: django internationalization subdomain django-urls

我有一个Django应用程序,目前支持多种语言。我想添加子域支持,以便“de.mysite.com”查询德语文章,而“mysite.com”查询英语(默认语言)。将有大约20个子域都指向同一个Django应用程序。

我有一个抽象模型,包含我的数据的所有字段和每种语言的派生模型。每种语言都有自己的数据库表,如下所示:

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

如何解析URL模式中的子域前缀,以便将其传递到文章视图中?或者我在处理视图时是否应该从请求中获取此信息?

3 个答案:

答案 0 :(得分:5)

django中的URL无法访问URL的域部分,因此这不是一个选项。 在每个视图中手动执行此操作是可行的,但不容易维护。

我认为自定义中间件解决方案可能更好用于检查中间件中的请求标头然后加载适当的语言(或者替换接受语言标头并让django做它的魔力)

localemiddleware可以使语言可用,然后您可以根据需要轻松地将其传递给模型/查询。

另外,如果我可能会问:为什么要将每个条目存储在单独的表/模型中?你不能只是在模型中添加语言字段并将所有内容存储在一个表中吗?因为购买20个左右的文章模型比单个模型更难维护。

更新:

我玩了一下,所需的中间件非常简单(尽管我的测试非常有限):

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

中使用

答案 1 :(得分: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...

答案 2 :(得分:0)

您可以使用这个易于使用的django-subdomains库。它还支持基于子域的URL路由和反转。