我有一个 Django 应用程序正在为(例如)example.com 提供服务。它包含许多子应用程序(例如)strength、speed 和 skill。 URL 方案类似于 http://example.com/strength、http://example.com/speed 和 http://example.com/技能。这就是我运行开发服务器的方式(使用 runserver)并且没有任何问题。
现在,在部署期间,我需要有映射到这些子应用程序的子域。更具体地说,我希望 http://x.example.com 映射到 http://example.com/x (对于 x 的上述值) 然后可以继续处理。
我用谷歌搜索了一下,找到了两种方法。
- 一个是获取一些中间件来获取 URL 的子域部分并将其保存在传递给我的 View 方法的
request对象中。然后我在我的应用程序逻辑中完成所有事情。 - 另一种是使用 Apache
mod_rewrite进行上述 URL 转换,然后让我的应用程序照常运行。
我选择了后者,因为它看起来更整洁,而且我认为我不必在我的核心应用程序中包含特定于部署的代码。
现在,我被一个无法真正找到出路的问题所困扰。在 skill 应用程序中,我有一个命名的 url skill_home。它是 http://example.com/skill。但是,在我部署后,skill_home URL 变为 http://skill.example.com/skill。 Django 将 /skill 附加到顶级域,这就是我得到的。如果我在此 URL 上执行 GET,mod_rewrite 会将其更改为 http://skill.example.com/skill/skill 并且它不起作用。
我的 mod_rewrite 片段看起来像这样
RewriteCond %{HTTP_HOST} !www.example.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www.)?skill.example.com [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) /skill/$1
我该如何巧妙地解决这个问题?
请您参考如下方法:
对于这个答案,我假设您愿意为每个子域执行 mod_rewrite。我认为这不适用于任何 子域(即您提到的 x)。
这将删除领先的 /skill/ 以便您的应用程序将继续工作:
RewriteCond %{HTTP_HOST} !www.example.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www.)?skill.example.com [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (/skill/)?(.*) /skill/$2
更新
好的,所以您要删除链接本身中 URL 的前导部分。
基本上,这意味着您必须编写自定义标签来替换 {% url %} 标签,如下所示:
import re
from django.template import Library
from django.template.defaulttags import URLNode, url
register = Library()
class SubdomainURLNode(URLNode):
def render(self, context):
domain = context['request'].get_host()
subdomain = re.sub(r'^www\.','',domain).split('.')[0]
path = super(SubdomainURLNode, self).render(context)
return re.sub(r'^/%s/' % subdomain, '/', path)
@register.tag
def subdomainurl(parser, token, node_cls=SubdomainURLNode):
"""Just like {% url %} but checks for a subdomain."""
node_instance = url(parser, token)
return node_cls(view_name=node_instance.view_name,
args=node_instance.args,
kwargs=node_instance.kwargs,
asvar=node_instance.asvar)
我已经在我的服务器上对此进行了测试,它似乎可以正常工作。
