7

假设我有一条路线“/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')

Pyramid 中是否有更优雅的东西可以做到这一点?

4

3 回答 3

11

Pyramid 有一种方法让HTTPNotFound视图自动附加斜线并再次测试路由以进行匹配(Django 的APPEND_SLASH=True工作方式)。看一眼:

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

As per this example, you can use config.add_notfound_view(notfound, append_slash=True), where notfound is a function that defines your HTTPNotFound view. If a view is not found (because it didn't match due to a missing slash), the HTTPNotFound view will append a slash and try again. The example shown in the link above is pretty informative, but let me know if you have any additional questions.

Also, heed the warning that this should not be used with POST requests.

There are also many ways to skin a cat in Pyramid, so you can play around and achieve this in different ways too, but you have the concept now.

于 2013-03-29T18:00:11.437 回答
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 参数。对于像这样的 URL /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')
于 2013-03-29T14:58:15.803 回答
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/ 都可以出现在浏览器中,具体取决于用户输入的内容。我并不介意,但重复渲染器路径也很尴尬。

于 2013-03-29T14:47:19.953 回答