Search code examples
pythonpyramid

Pyramid routing issue


I'm trying to setup a json service with a dynamic route: /action/{id}

I get a 404 when I navigate to: http://example.com:8080/action/test

Based on this documentation, it seems like my routing is configured correctly, but it is not.

Any idea on what I'm doing wrong here?

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.view import view_config


@view_config(route_name="action", renderer="json")
def run_action(self):
    id = self.request.matchdict['id']
    return {'id': id}


def main():
    config = Configurator()
    config.add_route('action', '/action/{id}')
    app = config.make_wsgi_app()
    return app


if __name__ == '__main__':
    app = main()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

Solution

  • Put a call to config.scan() in your main() function:

    def main():
        config = Configurator()
        config.add_route('action', '/action/{id}')
        config.scan()
        app = config.make_wsgi_app()
        return app
    

    The @view_config decorator doesn't do anything on its own. You must call config.scan(), which will then go and look for all @view_config declarations that have a route_name matching one of config's routes:

    config.add_route('foo')
    config.scan()
    

    will detect:

    @view_config(route_name="foo")
    

    Also, if you're going to have run_action as a standalone function (and not a class method), it should accept a single argument, 'request' (not 'self' as in your excerpt):

    @view_config(route_name="action", renderer="json")
    def run_action(request):
        id = request.matchdict['id']
        return {'id': id}
    

    If you do plan on having run_action as a class method, you need to initialize that class correctly, and decorate just the class method:

    class MyArbitraryClass():
        def __init__(self, request):
            self.request = request
    
        @view_config(route_name="action", renderer="json")
        def run_action(self):
            id = request.matchdict['id']
            return {'id': id}