Django - URL模板标记与子域断开

时间:2013-05-12 20:26:40

标签: django-templates subdomain django-1.5

我使用自定义中间件将子域映射到应用程序“urls.py”,方法是将相关的urls.py分配给request.urlconf变量。

除了{% url %}模板标记外,此方法正常 我得到了NoReverseMatch并且无法找出原因 调试页面显示reverse函数在view_name参数中收到一个值,因此它应该可以工作。

模板中的每个 {% url %}标记都会发生这种情况 如果我切换到类似文件夹的网址(例如myproject.com/sub,而不是sub.myproject.com),则代码可以正常工作。

对于为什么会发生这种情况以及如何解决这个问题的任何想法都非常感激。

1 个答案:

答案 0 :(得分:1)

好吧,在找不到我需要的东西之后,我找到了以下解决方案。 我放弃了request.urlconf映射,然后重写request.path_info 我在这里发布我的解决方案,万一有人遇到这个问题。

第一步,将以下中间件添加到您的项目中:

class SubdomainMiddleware:
    """Subdomain for Django"""
    def process_request(self, request):
        domain_parts = request.get_host().lower().replace('www.', '').split('.example.com', 1)
        if len(domain_parts) > 1 and domain_parts[0]:
            subdomain = domain_parts[0]
        else:
            subdomain = None

        if subdomain:
            if request.path_info[-1] != '/':
                request.path_info += '/'
            request.path_info = '/%s%s' % (subdomain, request.path_info)

接下来,添加以下代码覆盖reverse函数:

from django.conf import settings
from django.core import urlresolvers

_reverse = urlresolvers.reverse

def reverse(*args, **kwargs):
    # In case reversing a full url
    if args[0].startswith('http'):
        return args[0]
    # In case reversing a url name
    if '/' not in args[0]:
        url = _reverse(*args, **kwargs)
    else:
        # In case reversing a url path
        url = args[0]

    parts = url.strip('/').split('/', 1)
    subdomain = parts[0]
    path = parts[1] if len(parts) > 1 else ''
    protocol = 'http://' if settings.DEBUG else 'https://'
    return '%s%s%s/%s' % (protocol, subdomain, '.example.com', path)

urlresolvers.reverse = reverse

我把它放在自定义中间件所在的同一个文件中。

那就是它!

据我所知和测试,一切正常:倒车,重定向,模板{%url%}标签等。

注意:
我在这段代码中做了三个假设:

  • 域名为example.com。根据需要进行更改,将其放在settings.py中,适合您。
  • 子域映射到子文件夹。例如。 sub.example.com将转换为example.com/sub
  • 我的网站在任何地方使用SSL。因此,我只需检查自定义settings.DEBUG函数中的reverse值,看看它是否应使用httphttps

希望它有所帮助。