在金字塔中使用尾部斜杠的路线

时间:2013-03-29 14:35:41

标签: python url-routing pyramid

假设我有一条路线'/ foo / bar / baz'。 我还希望有另一个对应于'/ foo'或'/ foo /'的视图。 但是我不想系统地为其他路线添加尾部斜杠,仅用于/ foo和其他几个(/ buz但不是/ biz)

从我看到的我不能简单地定义具有相同route_name的两个路由。 我目前这样做:

config.add_route('foo', '/foo')
config.add_route('foo_slash', '/foo/')
config.add_view(lambda _,__: HTTPFound('/foo'), route_name='foo_slash')

金字塔中有更优雅的东西可以做到这一点吗?

3 个答案:

答案 0 :(得分:11)

Pyramid有HTTPNotFound次观看自动附加斜线并再次测试路线匹配的方式(Django的APPEND_SLASH=True工作方式)。看看:

<强> http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#redirecting-to-slash-appended-routes

根据此示例,您可以使用config.add_notfound_view(notfound, append_slash=True),其中notfound是定义HTTPNotFound视图的函数。如果找不到视图(因为它由于缺少斜杠而不匹配),HTTPNotFound视图将附加斜杠并重试。上面链接中显示的示例非常有用,但如果您有任何其他问题,请告诉我。

另外,请注意警告,这不应该与POST请求一起使用。

还有很多方法可以让金字塔中的猫皮肤变形,所以你可以用不同的方式来玩耍,但你现在有了这个概念。

答案 1 :(得分:3)

当我为我的项目寻找相同的东西时找到了这个解决方案

def add_auto_route(config,name, pattern, **kw):
    config.add_route(name, pattern, **kw)
    if not pattern.endswith('/'):
        config.add_route(name + '_auto', pattern + '/')
        def redirector(request):
            return HTTPMovedPermanently(request.route_url(name))
        config.add_view(redirector, route_name=name + '_auto')

然后在路线配置期间,

add_auto_route(config,'events','/events')

而不是config.add_route('events','/events')

基本上它是你方法的混合体。将定义名称以_auto结尾的新路由,并将其视图重定向到原始路由。

修改

该解决方案未考虑动态URL组件和GET参数。对于/abc/{def}?m=aasa之类的网址,使用add_auto_route()会引发密钥错误,因为redirector功能未考虑request.matchdict。以下代码就是这样做的。要访问GET参数,它还使用_query=request.GET

def add_auto_route(config,name, pattern, **kw):
    config.add_route(name, pattern, **kw)
    if not pattern.endswith('/'):
        config.add_route(name + '_auto', pattern + '/')
        def redirector(request):
            return HTTPMovedPermanently(request.route_url(name,_query=request.GET,**request.matchdict))
        config.add_view(redirector, route_name=name + '_auto')

答案 2 :(得分:1)

我找到了另一个解决方案。看起来我们可以链接两个@view_config。所以这个解决方案是可能的:

@view_config(route_name='foo_slash', renderer='myproject:templates/foo.mako')    
@view_config(route_name='foo', renderer='myproject:templates/foo.mako')
def foo(request):
   #do something

它的行为也与问题不同。问题的解决方案执行重定向,因此URL在浏览器中发生变化。在第二种形式中,/ foo和/ foo /都可以出现在浏览器中,具体取决于用户输入的内容。我真的不介意,但重复渲染器路径也很尴尬。