如何在金字塔复合项目中计算跨应用程序的URL?

时间:2019-04-19 22:41:50

标签: python url-routing pyramid

我正在使用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附加到{ {1}}。

我将config.add_route(...)应用用作网站home的登录页面,我想在/模板中执行类似request.route_url('app1.index')的操作来生成链接转到home中的index视图。但是,当我尝试这样做时,我从模板中得到了app1

我的解决方法是将路径硬编码到我的主页导航链接中,但是我不愿意这样做,因为这些路径已经在我的项目的.ini配置中定义了。

有没有办法在金字塔中做到这一点?

1 个答案:

答案 0 :(得分:1)

没有标准解决方案。我个人使用的方法是在配置文件中定义应用程序之间的交叉链接,并编写了一些代码以将它们作为静态路由自动注入到我的应用程序中(请参见static=True上的config.add_route),这使您可以使用request.route_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,
            )