Search code examples
pythonpyramid

Custom route predicates in Pyramid


I am using some custom predicates in one of my Pyramid application. Since Pyramid version 1.5, when starting the app, the following message is displayed:

my_project\__init__.py:110: DeprecationWarning: The "custom_predicates"
argument to Configurator.add_route is deprecated as of Pyramid 1.5.  Use
"config.add_route_predicate" and use the registered route predicate as a
predicate argument to add_route instead. See "Adding A Third Party
View,Route, or Subscriber Predicate" in the "Hooks" chapter
of the documentation for more information.

I would like to use the new method... but I cannot find one piece of advice in how to do that...

Even the doc illustrates the old method: https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#custom-route-predicates

I tried to defined my custom predicate in my my_project\__init__.py file, using something like:

def my_predicate(info, request):
    if request.something:
        return True
    return False

def main(global_config, **settings):
    ...
    config.add_route_predicate('my_predicate_name', my_predicate)

    config.add_route('my_route_name','/route_name/', 'my_predicate_name')
    ...

But that does not have any effect, I know that using 'my_predicate_name' is not the good way... I know that I am missing something, but I just cannot get what...

EDIT

If I change my code to:

config.add_route('my_route_name','/route_name/', my_predicate_name=True)

Then Pyramid throws the following error:

NameError: global name 'my_predicate_name' is not defined

It looks like the add_route_predicate does not have any effect...


Solution

  • This location in the documentation should explain how to implementat a custom predicate: http://docs.pylonsproject.org/projects/pyramid/en/master/narr/hooks.html#view-and-route-predicates

    Here is an additional example. The response in French should only be returned when lang=fr is in the query arguments otherwise the response in English matches by default.

    So / returns Hello and /?lang=fr returns bonjour.

    from wsgiref.simple_server import make_server
    from pyramid.config import Configurator
    from pyramid.response import Response
    
    
    def hello_world(request):
        return Response('Hello')
    
    
    class LanguagePredicate():
    
        def __init__(self, val, config):
            self.val = val
    
        def text(self):
            return 'lang = %s' % (self.val,)
    
        phash = text
    
        def __call__(self, context, request):
            return request.GET.get('lang') == self.val
    
    
    def hello_world_fr(request):
        return Response('bonjour')
    
    def main():
        config = Configurator()
    
        config.add_route_predicate('lang', LanguagePredicate)
    
        config.add_route('hello_fr', '/', lang='fr')
        config.add_route('hello', '/')    
    
        config.add_view(hello_world_fr, route_name='hello_fr')
        config.add_view(hello_world, route_name='hello')
    
    
        app = config.make_wsgi_app()
        return app
    
    if __name__ == '__main__':
        app = main()
        server = make_server('0.0.0.0', 6547, app)
        print ('Starting up server on http://localhost:6547')
        server.serve_forever()