假设我有一条路线'/ 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')
金字塔中有更优雅的东西可以做到这一点吗?
答案 0 :(得分:11)
Pyramid有HTTPNotFound
次观看自动附加斜线并再次测试路线匹配的方式(Django的APPEND_SLASH=True
工作方式)。看看:
根据此示例,您可以使用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 /都可以出现在浏览器中,具体取决于用户输入的内容。我真的不介意,但重复渲染器路径也很尴尬。