Django - URL模板标签在子域名下失效

3
我使用自定义中间件将子域名映射到应用程序的urls.py,通过将相关的urls.py分配给request.urlconf变量。这样可以很好地工作,但是{% url %}模板标签除外。我遇到了NoReverseMatch错误,并且想不出原因。调试页面显示reverse函数在view_name参数中收到一个值,所以它应该能够正常工作。每个模板中的{% url %}标签都会发生这种情况。如果我切换到文件夹式的URL(例如myproject.com/sub而不是sub.myproject.com),则标记可以正常工作。非常感谢任何关于为什么会发生这种情况以及如何解决的建议。

你可能想查看 https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts - 我还没有这样做..只是一个想法。 - karthikr
@karthikr,谢谢。我阅读了这个页面,但没有找到解决问题的方法。 - user1102018
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。因此,我只需在自定义的 reverse 函数中检查 settings.DEBUG 值,以确定它应该使用 http 还是 https

希望对您有所帮助。


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