Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pyramid_layout breaks view lookup #33

Open
tonthon opened this issue Jul 4, 2017 · 6 comments
Open

pyramid_layout breaks view lookup #33

tonthon opened this issue Jul 4, 2017 · 6 comments

Comments

@tonthon
Copy link

tonthon commented Jul 4, 2017

When using pyramid_layout with a non default layout, the request_param view predicates is not matched anymore.

Starting with the demo app, add following lines in views.py

@view_config(                                                                    
    route_name='home.mako',                                                    
    request_param='view=html',                                                   
    renderer='demo:templates/home2.mako',                                      
)                                             
@view_config(                                                                    
    route_name='home.jinja2',                                                    
    request_param='view=html',                                                   
    renderer='demo:templates/home2.jinja2',                                      
)                                                                                
def home2(request):                                                              
    return {}  

Add a home2.mako and a home2.jinja2 in the demo/templates directory

<div>It works</div>

Restart the demo server

If you go to
http://0.0.0.0:6543/?view=html
you get the expected 'It works' text.

If you go to
http://0.0.0.0:6543/home.jinja2?view=html
You fill on the home page and not on the expected one.

@stevepiercy
Copy link
Member

This sounds like a route matching issue in your code. There is a usage pattern to register routes, as shown in the demo app that might help.

@tonthon
Copy link
Author

tonthon commented Jul 5, 2017

As said here above, the issue is easily reproducible starting with the demo app. It has nothing to do with route registration, but with the fact that the layout predicate should not influence the way a view is matched or not (in fact it shoud not be a predicate).

@tonthon
Copy link
Author

tonthon commented Jul 5, 2017

Here a test repo including the changes listed here above (more information in the README).

https://github.com/tonthon/test-pyramid-layout-33

@digitalresistor
Copy link
Member

This is due to the way that view matching works in Pyramid, and due to the fact that layout is a predicate.

Pyramid matches views based upon some non-predicate information (IIRC permissions/accept are the only two) after that it matches based on longest predicate match:

@view_config(
    route_name='home.mako',
    renderer='demo:templates/home.mako'
    )

Predicates:

  • route_name
@view_config(
    route_name='home.chameleon',
    renderer='demo:templates/home.pt',
    layout='chameleon'
    )

Predicates:

  • route_name
  • layout
@view_config(
    route_name='home.jinja2',
    renderer='demo:templates/home.jinja2',
    layout='jinja2'
    )

Predicates:

  • route_name
  • layout

Then here comes your home2:

@view_config(
    route_name='home.mako',
    request_param='view=html',
    renderer='demo:templates/home2.mako',
)

Predicates:

  • route_name
  • request_param
@view_config(
    route_name='home.jinja2',
    request_param='view=html',
    renderer='demo:templates/home2.jinja2',
)

Predicates:

  • route_name
  • request_param

Pyramid when given:

http://0.0.0.0:6543/jinja2?view=html

Will match in the order that views were registered, so since there are no permissions or accept that are not predicates, we basically ask for all views and start narrowing things down.

  • route_name matches 'jinja2'
  • layout always returns True and thus always matches

The next view that might match would be:

  • route_name matches 'jinja2'
  • request_param has 'view' equal 'html'

However, since both have a predicate length of 2 (longest match wins), it picks the first view found.

You can see that with pviews:

(env) alexandra:test-pyramid-layout-33 xistence$ pviews development.ini /jinja2?view=html

URL = /jinja2?view=html

    context: <pyramid.traversal.DefaultRootFactory object at 0x105344ef0>
    view name: 

    View:
    -----
    demo.views.home
    view predicates (layout = jinja2)

    View:
    -----
    demo.views.home2
    view predicates (request_param view=html)

If instead if we add the layout predicate explicitly to the last view:

@view_config(
    route_name='home.jinja2',
    request_param='view=html',
    renderer='demo:templates/home2.jinja2',
    layout='jinja2'
)

Then it has the following predicates:

  • route_name
  • request_param
  • layout

And thus it wins since it has the longest predicate chain:

(env) alexandra:test-pyramid-layout-33 xistence$ pviews development.ini /jinja2?view=html

URL = /jinja2?view=html

    context: <pyramid.traversal.DefaultRootFactory object at 0x10b0faba8>
    view name: 

    View:
    -----
    demo.views.home2
    view predicates (request_param view=html, layout = jinja2)

    View:
    -----
    demo.views.home
    view predicates (layout = jinja2)

The reason the mako example works, is because the mako view_config only has a single predicate, and thus with view=html the request_param predicate matches and thus it has a longer predicate chain.


tl;dr: pyramid_layout should make layout a view deriver instead, so that it doesn't affect route matching because the predicate is not actually a predicate.

@s4msung
Copy link

s4msung commented Apr 1, 2019

any progress on this topic?

@stevepiercy
Copy link
Member

@s4msung nope. Help is wanted. We'd accept a PR with tests, documentation updates, and a signed CONTRIBUTORS.txt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants