Search code examples
pythonpyramid

Adding views using directives and actions in pyramid


I want to create a directive on a pyramid configurator that allows an application importing my library to add a view connected to a specific route with certain defaults.

My first attempt (modeled off of the examples given in the pyramid docs):

def status_view_directive(config, view, **view_config_kwargs):
    def register_status_view():
        config.add_view(
            view=view,
            route_name='status',
            **view_config_kwargs
        )
    config.action('a_discriminator', register_status_view)

if __name__ == '__main__':
    config = Configurator()
    config.add_route('status', '/status')
    config.add_directive('add_status_view', status_view_directive)
    config.add_status_view('some_view', **some_kwargs)
    return config.make_wsgi_app()

It doesn't work. Whenever I try to access the view I get a 404 back.

If I modify the code to the following, it works as expected:

def status_view_directive(config, view, **view_config_kwargs):
    config.add_view(
        view=view,
        route_name='status',
        **view_config_kwargs
    )

if __name__ == '__main__':
    config = Configurator()
    config.add_route('status', '/status')
    config.add_directive('add_status_view', status_view_directive)
    config.add_status_view('some_view', **some_kwargs)
    return config.make_wsgi_app()

I just lost a couple hours trying to figure this out. Does anyone know why the first snippet doesn't work?


Solution

  • This is what's happening:

    • A register_status_view action is registered when your directive is called.

    • When Pyramid executes actions, it executes this action.

    • However, this action calls a directive that itself registers an action. But action execution is not recursive. Actions that are registered as the result of an action execution are dropped on the floor.

    We have some plans to resolve this in an upcoming Pyramid release. However, for now, you can probably just do this instead:

    def status_view_directive(config, view, **view_config_kwargs):
        config.add_view(
            view=view,
            route_name='status',
            **view_config_kwargs
            )