我正在使用Pyramid开发一个由多个应用程序组成的大型Web项目,使用复合应用程序功能连接在一起,我想在我的主页上生成导航链接以指向不同的应用程序。我的INI文件是这样开始的:
[composite:main]
use = egg:Paste#urlmap
/ = home
/app1 = myapp1
/app2 = myapp2
[app:home]
use = egg:myproject#home
[app:myapp1]
use = egg:myproject#myapp1
[app:myapp2]
use = egg:myproject#myapp2
...
在给定的应用程序中,我使用request.route_url('view_name')
生成URL,并且代码正确地将/
或/app1
或/app2
预先添加到config.add_route(...)
在应用程序中定义的任何URL。
我使用home
应用程序作为/
网站的登陆页面,我想在request.route_url('app1.index')
模板中执行类似home
的操作,以生成index
中app1
视图的链接。然而,当我尝试这个时,我从模板中获得KeyError: 'No such route named app1.index'
。
我的解决方法是将路径硬编码到我的主页导航链接中,但我宁愿不这样做,因为这些路径已经在我的项目的.ini配置中定义。
有没有办法在金字塔中做到这一点?
有一个标准的解决方案。我个人使用的方法是在我的配置文件中定义应用程序之间的交叉链接,我写了一些代码,以自动将它们作为静态路由注入我的应用程序(请参阅static=True
上的config.add_route
),这允许您使用request.route_url
生成外部的URL你的应用。
因此,我构建了一个如下所示的配置:
[composite:main]
use = egg:Paste#urlmap
/ = home
/app1 = myapp1
/app2 = myapp2
[app:home]
use = egg:myproject#home
links =
app1 /app1
app2 /app2
[app:myapp1]
use = egg:myproject#myapp1
links =
home /
app2 /app2
[app:myapp2]
use = egg:myproject#myapp2
links =
home /
app1 /app1
您可能会发现它很乏味但我喜欢它在每个应用程序基础上提供的控件。您也可以在文件的[DEFAULT]
部分中定义它,并在应用程序之间继承它。
这个想法是这个配置允许我做request.route_url('app1')
。
我使用这段代码(将它放入一个名为app_links.py
的文件中,并通过config.include('.app_links')
包含它:
from urllib.parse import urlparse
from pyramid.settings import aslist
def link_pregenerator(request, elements, kwargs):
kwargs['_app_url'] = request.host_url
return elements, kwargs
def includeme(config):
settings = config.get_settings()
links = aslist(settings.get('links', ''), flatten=False)
for name, pattern in (item.split(' ', 1) for item in links):
parsed = urlparse(pattern)
if parsed.hostname:
config.add_route(name, pattern, static=True)
else:
config.add_route(
name, pattern,
pregenerator=link_pregenerator,
static=True,
)