Routes with trailing slashes in Pyramid

拥有回忆 提交于 2019-12-04 22:24:39

问题


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 ?


回答1:


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



回答2:


Pyramid has a way for HTTPNotFound views to automatically append a slash and test the routes again for a match (the way Django's APPEND_SLASH=True works). Take a look at:

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.




回答3:


I found another solution. It looks like we can chain two @view_config. So this solution is possible:

@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

Its behavior is also different from the question. The solution from the question performs a redirect, so the url changes in the browser. In the second form both /foo and /foo/ can appear in the browser, depending on what the user entered. I don't really mind, but repeating the renderer path is also awkward.



来源:https://stackoverflow.com/questions/15705399/routes-with-trailing-slashes-in-pyramid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!