我该如何在Django中根据域名或顶级域名设置urlpatterns?

8
如何在Django中根据域名或TLD设置urlpatterns?
对于某些链接,亚马逊会根据其网站的顶级域名以本地语言显示URL。 http://www.amazon.de/bücher-buch-literatur/ (de:books => bücher) http://www.amazon.fr/Nouveautés-paraître-Livres/(fr:books => Livres)

http://www.amazon.co.jp/和書-ユーズドブッ-英語学習/ (jp:书籍 => 和书)

(链接不完整,仅为示例。)

在urls.py中是否有可能获取主机名?(请求对象在urls.py中不可用),或者在中间件的process_request中使用它并在urls.py中使用它(如何实现?)

还有其他建议如何实现这一点吗?

#---------- pseudocode ---------- 

website_tld = get_host(request).split(".")[-1]

#.fr French  : Books : Livres
#.de German : Books : Bücher

if website_tld == "fr":
    lang_word = "Livres"
elif website_tld == "de":
    lang_word = "Bücher"
else:
    lang_word = "books"

urlpatterns = patterns('',
                       url(r'^%s/$' % lang_word,books_view, name="books"),
                       )

URL模式需要根据顶级域名(TLD)构建,然后在模板中使用<a href="{% url books %}" >{% trans "books" %}</a>来呈现HTML,例如<a href="Bücher">Bücher</a><a href="Livres">Livres</a>。

3个回答

15

您需要在网站服务器级别上执行此操作(例如使用Apache中的mod_rewrite),或者使用中间件(例如此代码片段)。

另请参见此SO问题


更新:在您的评论后,我考虑了一些更多的事情。我喜欢Carl Meyer的答案,但是后来意识到它不能正确地处理{% url %}反向。所以这就是我会做的:

多个站点: 您需要使用Django网站框架。这意味着使用Django管理员为每种语言创建站点实例。

多个设置: 每种语言站点还将拥有自己的settings.py。每个站点之间唯一的区别将是SITE_IDROOT_URLCONF设置,因此为了遵循DRY原则,您应该将通用设置保存在不同的文件中,并像这样将其导入主文件:

# settings_fr.py
SITE_ID = 1
ROOT_URLCONF = 'app.urls_fr'
from settings_common import *

# settings_de.py
SITE_ID = 2
ROOT_URLCONF = 'app.urls_de'
from settings_common import *

多个URL配置文件:如上所示,每个站点都有一个URL配置文件:

# urls_fr.py
urlpatterns = patterns('',
    url(r'^Livres/$', books_view, name="books"),
)

# urls_de.py
urlpatterns = patterns('',
    url(r'^Bücher/$', books_view, name="books"),
)

这种方式中,URL名称(在本例中为“books”)对于所有语言都是相同的,因此{% url books %}将正确反转并且域名将是Site对象的SITE_ID字段的domain_name。

多个Web服务器实例:为了使每个站点正常工作,它们需要各自拥有自己的服务器实例。对于Apache + mod_wsgi,这意味着每个SITE都需要像这样一个不同的WSGI应用程序:

# site_fr.wsgi
import os, sys, django.core.handlers.wsgi
os.environ['DJANGO_SETTINGS_MODULE'] = 'app.settings_fr'
application = django.core.handlers.wsgi.WSGIHandler()

...还有匹配每个站点的Apache虚拟主机:

<VirtualHost *:80>
    ServerName mybooks.fr
    WSGIScriptAlias / /path/to/site_fr.wsgi
    ...
</VirtualHost>

希望这很清楚 :)


谢谢Van,也许我没有理解你提到的另一个问题的重点。在这里,需要根据tld构建url模式,然后在模板中使用<a href="{% url books %}" >{% trans "books" %</a>}将html渲染为<a href="Bücher">Bücher</a>或<a href="Livres">Livres</a>。 - X10
2
Van,感谢您如此详细的写作! - X10
@Van 在一些答案中,人们建议在单个Django项目中使用django-subdomains来使用多个子域名。看起来这会简化事情。但是从文档中我没有找到如何使用它。您能否提供使用该解决方案的方法?使用django-subdomains还是您上面描述的方式更好? - Ashish Gupta

8

您可以通过中间件实现此操作,该中间件通过request.META ['HTTP_HOST']检索TLD并将其添加到request.path中;然后您的根URLconf可以根据TLD作为第一个URL路径段切换到特定于语言的URLconfs。类似于以下内容(未经测试!):

class PrependTLDMiddleware:
""" Prepend the top level domain to the URL path so it can be switched on in 
a URLconf. """

def process_request(self, request):
    tld = request.META['HTTP_HOST'].split('.')[-1]
    request.path = "/%s%s" % (tld, request.path)

在您的URLconf中:

urlpatterns = patterns('',
    url(r'^de/' include('de_urls')),
    url(r'^fr/', include('fr_urls')),
    url(r'^[^/]+/', include('en_urls'))
)

然后,de_urls.py、fr_urls.py和en_urls.py可以分别包含所需的所有URL,并以相应的语言进行标识。

-1
在Django中有一个名为“Sites”的表格。也许你可以从中得到一些启示?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接