Search code examples
pythonurl-routingpyramid

Routes with trailing slashes in Pyramid


Let's say I have a route '/foo/bar/baz'. I would also like to have another view corresponding to '/foo' or '/foo/'. But I don't want to systematically append trailing slashes for other routes, only for /foo and a few others (/buz but not /biz)

From what I saw I cannot simply define two routes with the same route_name. I currently do this:

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

Is there something more elegant in Pyramid to do this ?


Solution

  • Found this solution when I was looking for the same thing for my project

    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')
    

    And then during route configuration,

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

    Rather than doing config.add_route('events','/events')

    Basically it is a hybrid of your methods. A new route with name ending in _auto is defined and its view redirects to the original route.

    EDIT

    The solution does not take into account dynamic URL components and GET parameters. For a URL like /abc/{def}?m=aasa, using add_auto_route() will throw a key error because the redirector function does not take into account request.matchdict. The below code does that. To access GET parameters it also uses _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')