可能是一个简单的问题,我只是遗漏了一些东西,但是我的想法很难理解。
我有Django项目为几个具有不同sessions.py
和完全不同ROOT_URLCONF
的网站提供服务。一个站点处理用户注册,身份验证和配置文件设置,其他站点(在另一个域上)充当文件管理器等。站点共享相同的数据库,媒体和模板。所有站点都共享相同的用户群,实现了一种透明的单点登录/单点登录机制。它就像一个大型网站,跨越多个领域。
问题是,我的模板中有很多{% url %}
个标签,当模板在其他网站上使用时,它们不起作用。我希望尽可能避免硬编码网址。
例如,在网站A(a.example.org)上我有一个
url('^users/$', 'example.accounts.list_users', name='list_users'),
在A的URLconf中输入。然后,在某些global_menu.html
模板中,我有{% url list_users %}
,显然效果很好,导致“/users/
”。
现在,有站点B(b.example.org),与A共享许多内部组件。为了具有共同的外观,我想在站点B上使用相同的global_menu.html
并希望{{ 1}}输出“{% url list_users %}
”。我能做到这一点的最佳方式是什么?
目前,我正在为每个网站使用单独的http://a.example.org/users/
,但这违反了DRY原则,并不是很方便。而且,是的,我正在使用Django的global_menu.html
框架,在contrib.sites
中为每个网站定义了不同的SITE_ID
,但实际上还没有在其他地方使用它。
更新:目前我正在考虑重新实现settings.py
代码或猴子修补url
,以调用原始代码,并在异常情况下执行其他查找“外国URI列表”。如果已经存在这样的事情 - 我会很高兴听到。
提前感谢您的回答!
答案 0 :(得分:12)
我通过使用自定义函数覆盖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
然后在settings.py
中列出URLconf,如下所示:
ROOT_URLCONF = 'project.urls_a'
EXTERNAL_URLCONFS = (
('http://b.example.com/', 'project.urls_b'),
)
答案 1 :(得分:2)
是的,你需要制作自己的{% url %}
标签,该标签使用它自己的反转方法。
例如,要专门针对site_a urlconf进行反转,那么您可以使用如下方法:
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)
答案 2 :(得分:1)
使用@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文件中以便在启动时执行
答案 3 :(得分:0)
我建议做两处修改。 (1)如果您还没有将模板移动到公共目录(而不是每个应用程序)。 (2)调查新添加的URL namespaces功能。
第一个更改将允许您拥有一个公共基本模板,并有选择地为各种应用/网站覆盖它。第二个可能会使您的网址“更干燥”。