pyramidchameleon

Pyramid's Chameleon renderer template can't be found using relative path


I'm new to pyramid. When trying to use chameleon as the templating engine, it fails to find the template when specified with a relative path - It is looking for it at env35/lib/python3.5/site-packages/pyramid/ where env35 is the virtual environment I created. It will work however if the full path is specified. It will also work using a relative path using jinja2 as the templating engine. Why can I not use a chameleon template using relative path?

From the manual

add_view(...., renderer,...)

This is either a single string term (e.g. json) or a string implying a path or asset specification (e.g. templates/views.pt) naming a renderer implementation. If the renderer value does not contain a dot ., the specified string will be used to look up a renderer implementation, and that renderer implementation will be used to construct a response from the view return value. If the renderer value contains a dot (.), the specified term will be treated as a path, and the filename extension of the last element in the path will be used to look up the renderer implementation, which will be passed the full path. The renderer implementation will be used to construct a response from the view return value.

Note that if the view itself returns a response (see View Callable Responses), the specified renderer implementation is never called.

When the renderer is a path, although a path is usually just a simple relative pathname (e.g. templates/foo.pt, implying that a template named "foo.pt" is in the "templates" directory relative to the directory of the current package of the Configurator), a path can be absolute, starting with a slash on UNIX or a drive letter prefix on Windows. The path can alternately be a asset specification in the form some.dotted.package_name:relative/path, making it possible to address template assets which live in a separate package.

The renderer attribute is optional. If it is not defined, the "null" renderer is assumed (no rendering is performed and the value is passed back to the upstream Pyramid machinery unmodified).

Here are the steps I undertook to set up my environment...

export VENV=~/Documents/app_projects/pyramid_tutorial/env35
python3 -m venv $VENV
source $VENV/bin/activate  #activate the virtual environment
pip install --upgrade pip
pip install pyramid 
pip install wheel
pip install pyramid_chameleon
pip install pyramid_jinja2

My file structure:

pyramid_tutorial
    env35
        bin
        ...
    templates
        hello.jinja2
        hello.pt
    test_app.py

test_app.py:

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

def hello(request):
    return dict(name='Bugs Bunny')

if __name__ == '__main__':
    config = Configurator()
    config.include('pyramid_chameleon')
    config.include('pyramid_jinja2')

    #This does not work... http://localhost:6543/chameleon
    config.add_route('hello_world_1', '/chameleon')
    config.add_view(hello, route_name='hello_world_1', renderer='templates/hello.pt')
    # ValueError: Missing template asset: templates/hello.pt (/home/david/Documents/app_projects/pyramid_tutorial/env35/lib/python3.5/site-packages/pyramid/templates/hello.pt)

    #This works... http://localhost:6543/chameleon2
    config.add_route('hello_world_2', '/chameleon2')
    config.add_view(hello, route_name='hello_world_2', renderer='/home/david/Documents/app_projects/pyramid_tutorial/templates/hello.pt')

    #This works... http://localhost:6543/jinja
    config.add_route('hello_world_3', '/jinja')
    config.add_view(hello, route_name='hello_world_3', renderer='templates/hello.jinja2')

    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 6543, app)
    print ('Serving at http://127.0.0.1:6543')
    server.serve_forever()

hello.pt:

<p>Hello <strong>${name}</strong>! (Chameleon renderer)</p>

hello.jinja2:

<p>Hello <strong>{{name}}</strong>! (jinja2 renderer)</p>

Solution

  • It will work if you specify renderer=__name__ + ':templates/hello.pt'. The resolution logic doesn't work in this case because the file is not being executed as a python package and thus some weird stuff can occur. pyramid_chameleon could likely be updated with better support here but by far the common case for real apps is to write your code as a package which will work as expected.

    It might also work if you tweak things slighty run your script as a module via python -m test_app.