joshlk
joshlk

Reputation: 1651

All addresses to go to a single page (catch-all route to a single view) in Python Pyramid

I am trying to alter the Pyramid hello world example so that any request to the Pyramid server serves the same page. i.e. all routes point to the same view. This is what iv got so far:

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
    return Response('Hello %(name)s!' % request.matchdict)

if __name__ == '__main__':
    config = Configurator()
    config.add_route('hello', '/*')
    config.add_view(hello_world, route_name='hello')
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()
   

All iv done is change the line (from the hello world example):

    config.add_route('hello', '/hello/{name}')

To:

    config.add_route('hello', '/*')

So I want the route to be a 'catch-all'. Iv tried various variations and cant get it to work. Does anyone have any ideas?

Thanks in advance

Upvotes: 6

Views: 1009

Answers (2)

Sergey
Sergey

Reputation: 12417

The syntax for the catchall route (which is called "traversal subpath" in Pyramid) is *subpath instead of *. There's also *traverse which is used in hybrid routing which combines route dispatch and traversal. You can read about it here: Using *subpath in a Route Pattern

In your view function you'll then be able to access the subpath via request.subpath, which is a tuple of path segments caught by the catchall route. So, your application would look like this:

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
    if request.subpath:
        name = request.subpath[0]
    else:
        name = 'Incognito'
    return Response('Hello %s!' % name)

if __name__ == '__main__':
    with Configurator() as config:
        config.add_route('hello', '/*subpath')
        config.add_view(hello_world, route_name='hello')
        app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8081, app)
    server.serve_forever()

Don't do it via custom 404 handler, it smells of PHP :)

Upvotes: 10

Peter Tirrell
Peter Tirrell

Reputation: 3003

You could create a custom error handler (don't remember off the top of my head but it was in the Pyramid docs) and capture HTTP 404 errors, and redirect/render your catch-all route from there.

The link I'm thinking of: http://docs.pylonsproject.org/projects/pyramid//en/latest/narr/hooks.html

I've done something like this:

from pyramid.view import (
    view_config,
    forbidden_view_config,
    notfound_view_config
    )

from pyramid.httpexceptions import (
    HTTPFound,
    HTTPNotFound,
    HTTPForbidden,
    HTTPBadRequest,
    HTTPInternalServerError
    )

import transaction
import traceback
import logging

log = logging.getLogger(__name__)

#region Custom HTTP Errors and Exceptions
@view_config(context=HTTPNotFound, renderer='HTTPNotFound.mako')
def notfound(request):
    if not 'favicon' in str(request.url):
        log.error('404 not found: {0}'.format(str(request.url)))
        request.response.status_int = 404
    return {}

I think you should be able to redirect to a view from within there.

Upvotes: -1

Related Questions