Django的跨站点反向网址(Django cross-site reverse URLs)

2019-07-31 07:40发布

也许简单的问题,我只是失去了一些东西,但我坚持的想法。

我有几个服务站点,不同的Django项目sessions.py和完全不同的ROOT_URLCONF秒。 一个网站处理用户注册,认证和配置文件设置,其他网站(另一个域)作为文件管理器等。 站点共享同一数据库,媒体和模板。 所有网站都共享相同的用户群,实现某种透明的单点登录/单点登录关闭装置。 它就像一个大工地,跨多个域跨越。

问题是,我有很多的{% url %}在我的模板标签,当模板的其他网站上使用他们不工作。 我想,以避免硬编码的URL尽可能。

例如,在站点A(a.example.org)我有一个

url('^users/$', 'example.accounts.list_users', name='list_users'),

表中的内容的URL配置。 于是,在一些global_menu.html模板我有{% url list_users %} ,显然它的作品完美,造成“ /users/ ”。

现在,有网站B(b.example.org),与A分享了很多内部的有共同的外观和感觉我想用同样的global_menu.html现场B和希望{% url list_users %}到输出“ http://a.example.org/users/ ”。 什么是我能做到这一点的最好方法是什么?

目前,我使用单独的global_menu.html为每个站点,但这违反了DRY原则,而不是真的很方便。 而且,是的,我使用的Django的contrib.sites框架具有鲜明SITE_ID定义小号settings.py为每个站点,但尚未实际使用的任何其他地方。

更新 :目前我正在考虑重新实现的url标签或猴子修补reverse()调用原单,并在例外执行额外的一些“洋地址列表”中查找。 如果已经存在这样的事 - 我很乐意听到的。

预先感谢您的答案!

Answer 1:

我已经通过覆盖实现了它django.core.urlresolvers.reverse与我的自定义函数:

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

__real_reverse = urlresolvers.reverse

def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None):
    try:
        return __real_reverse(viewname, urlconf, args, kwargs, prefix)
    except urlresolvers.NoReverseMatch, no_match:
        external_urlconfs = getattr(settings, 'EXTERNAL_URLCONFS', [])
        for p, c in external_urlconfs:
            c = urlresolvers.RegexURLResolver(r'^/', c)
            try:
                return p + c.reverse(viewname, *args, **kwargs)
            except urlresolvers.NoReverseMatch:
                pass
        raise no_match

urlresolvers.reverse = reverse

随后上市的URLconf在settings.py是这样的:

ROOT_URLCONF = 'project.urls_a'

EXTERNAL_URLCONFS = (
    ('http://b.example.com/', 'project.urls_b'),
)


Answer 2:

是的,你需要使自己的{% url %}标签,它使用它自己反转法。

例如,专门针对反向的Site_A的URL配置,那么你可以使用的方法是这样的:

from django.core.urlresolvers import reverse
import site_a

def site_a_reverse(viewname, args=None, kwargs=None):
    # If your sites share the same database, you could get prefix from Site.objects.get(pk=site_a.settings.SITE_ID)
    prefix = 'http://a.example.com/'  # Note, you need the trailing slash
    reverse(viewname, urlconf=site_a.urls, args=args, kwargs=kwargs, prefix=prefix)


Answer 3:

反向利用@drdaeman相同的设置覆盖Django的1.7.x

# -*- coding: utf-8 -*-
from django.core import urlresolvers
from django.conf import settings

__real_reverse = urlresolvers.reverse


def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None):
    try:
        return __real_reverse(viewname, urlconf, args, kwargs, prefix, current_app)
    except urlresolvers.NoReverseMatch, no_match:
        external_urlconfs = getattr(settings, 'EXTERNAL_URLCONFS', [])
        for p, c in external_urlconfs:
            urlconf = c
            try:
                return p + __real_reverse(viewname, urlconf, args, kwargs, prefix, current_app)
            except urlresolvers.NoReverseMatch:
                pass
        raise no_match

urlresolvers.reverse = reverse

我把代码在urls.py文件在启动时执行



Answer 4:

我建议做两个变化。 (1)移动模板到一个目录下(而不是每个应用程序),如果您已经没有。 (2)调查新加入的URL 命名空间功能。

第一个变化将让你有一个共同的基础模板,并有选择地覆盖它的各种应用程序/网站。 第二个可能有助于使你的URL“干燥”。



文章来源: Django cross-site reverse URLs