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>
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
.