3

我使用自定义中间件urls.py通过将相关分配给urls.py变量来request.urlconf将子域映射到应用程序。

这工作正常,除了{% url %}模板标签。
我得到一个NoReverseMatch并且无法弄清楚为什么。
调试页面显示该reverse函数在view_name参数中接收到一个值,因此它应该可以工作。

这发生在模板中的每个标签上。 如果我切换到类似文件夹的 url(例如,而不是),标签可以正常工作。 {% url %}
myproject.com/subsub.myproject.com

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

4

1 回答 1

2

好吧,在没有找到我需要的东西之后,我来到了以下解决方案。我放弃了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函数中的值,看看它是否应该使用httpor https

希望能帮助到你。

于 2013-05-16T14:15:00.110 回答