Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 534
ascobol Avatar asked Mar 29 '13 14:03

ascobol


People also ask

Does a trailing slash impact SEO?

A trailing slash at the end of a URL on your website can cause issues with duplicate content if not dealt with correctly. Put simply, Google doesn't like seeing the same content on different pages. It can be confusing for both search engines and users.

What is a trailing slash in URL?

A trailing slash is a forward slash (“/”) placed at the end of a URL such as domain.com/ or domain.com/page/. The trailing slash is generally used to distinguish a directory which has the trailing slash from a file that does not have the trailing slash.

What is Matchdict?

A matchdict is the dictionary representing the dynamic parts extracted from a URL based on the routing pattern. It is available as request.matchdict . For example, the following pattern defines one literal segment ( foo ) and two replacement markers ( baz , and bar ):


2 Answers

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.

like image 181
Raj Avatar answered Sep 28 '22 00:09

Raj


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')
like image 30
RedBaron Avatar answered Sep 28 '22 00:09

RedBaron