【问题标题】:Django, subdomains and mod_rewrite. URLs messing up on deployment setupsDjango、子域和 mod_rewrite。 URL 搞乱了部署设置
【发布时间】:2011-03-28 13:40:18
【问题描述】:

我有一个由(比如)example.com 提供的 Django 应用程序。它包含许多子应用程序(比如)strengthspeedskill。 URL 方案类似于http://example.com/strengthhttp://example.com/speedhttp://example.com/skill。这就是我运行我的开发服务器的方式(使用runserver)并且没有任何问题。

现在,在部署期间,我需要将子域映射到这些子应用程序。更具体地说,我希望http://x.example.com 映射到http://example.com/x(对于x 的上述值),然后可以继续处理。

我用谷歌搜索了一下,发现了两种方法。

  • 一种是获取一些中间件来获取 URL 的子域部分,并将其保存在传递给我的视图方法的 request 对象中。然后我在我的应用程序逻辑中完成整个事情。
  • 另一种是使用Apachemod_rewrite做上面的URL翻译,然后让我的应用程序照常运行。

我选择了后者,因为它看起来更整洁,而且我认为我不必在我的核心应用程序中包含特定于部署的代码。

现在,我被一个无法真正解决的问题所困扰。在skill 应用程序中,我有一个名为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_rewritesn-ps 长这样

RewriteCond %{HTTP_HOST} !www.example.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www.)?skill.example.com [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) /skill/$1 

如何巧妙地解决这个问题?

【问题讨论】:

  • 拥有一个通用的mod_rewrite 定义来处理将您的子域映射到您的子应用程序路径并不难,但只要 Django 将这些路径附加到您的 URL,就不可能解决问题.我个人只熟悉这个问题的mod_rewrite 方面,但是有没有办法阻止 Django 附加该路径? (嗯,我想这确实是你问题的一部分,但我想我会问)
  • 好吧,我想实际上将每个 sub-application 作为单独的顶级应用程序运行,然后将它们从 / 中服务。不过看起来太重了。

标签: python django mod-rewrite subdomain


【解决方案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)

我已经在我的服务器上对此进行了测试,它似乎可以工作。

【讨论】:

  • 嗯很有趣...我能想到 2 个问题。一个是你已经提到的。我将有一些动态创建的域。第二个是虽然应用程序可以运行,但当我将鼠标悬停在某些链接上时,我仍然会看到像 http://skill.example.com/skill 这样的脏 URL。这有点丑。
  • 嗯...我一定不明白您的应用程序是如何设置的。我假设 /skill/ 是技能应用程序的前缀。在这种情况下,您需要在 URL 中使用它才能正常工作。
  • 是的。但是对于像 http://skill.example.com 这样的 URL,已经提到了 skill 部分。如果开发服务器在(比如说)127.0.0.1:8080 上运行,我可以说http://127.0.0.1:8080/skill/page1 并且它会工作。使用已部署的设置,我想说http://skill.example.com/page1。这将正常工作。然而,当我将鼠标悬停在page1 的链接上时,我会看到类似http://skill.example.com/skill/page1 的东西,看起来很丑。
  • 是的,问题是如果你使用带有命名 URL 的 {% url %},Django 将使用你给它的规则,所以如果路径是 /skill/page1 这就是你的会看到。我已经用我认为对你有用的东西修改了我的答案。
  • 让我试一试。我会让你知道它是否有效。你最初的解决方案对我有用(有丑陋的 URL 问题),我被一些东西束缚住了。一旦我尝试,我会在这里发帖。谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 2020-03-21
  • 2016-01-12
相关资源
最近更新 更多