Pylons encourages a good separation
between the model, the controllers, and the views. It also is very
flexible about using different template engines for different views.
This note discusses a way for how to set and use
Evoque Templating as the default template engine in
a Pylons (minimum version 0.9.7) application.
Let's assume we create a site from scratch, let's call it evoque_site.
When asked, enter the template_engine as follows:
$ paster create --template=pylons evoque_site
Selected and implied templates:
Pylons#pylons Pylons application template
Variables:
egg: evoque_site
package: evoque_site
project: evoque_site
Enter template_engine (mako/genshi/jinja/etc: Template language) ['mako']: evoque
Enter sqlalchemy (True/False: Include SQLAlchemy 0.4 configuration) [False]:
adjust application files
We will then need to add the following codes to the files/functions indicated:
evoque_site.config.environment.load_environment(global_conf, app_conf)
# Evoque Templating:
# http://evoque.gizmojo.org/ext/pylons/
# http://evoque.gizmojo.org/usage/api/
import logging
from evoque.domain import Domain
evoque_domain = Domain(
# root folder for the default template collection, must be abspath;
# as default use pylon's first templates folder
os.path.join(root,
app_conf.get("evoque.default_dir") or paths['templates'][0]),
# whether evaluation namespace is restricted or not
restricted = app_conf.get("evoque.restricted")=="true",
# how should any evaluation errors be rendered
# int 0 to 4, for: [silent, zero, name, render, raise]
errors = int(app_conf.get("evoque.errors", 3)),
# evoque logger; additional setings should be specified via the pylons
# config ini file, just as for any other logger in a pylons application
log = logging.getLogger("evoque"),
# [collections] int, max loaded templates in a collection
cache_size = int(app_conf.get("evoque.cache_size", 0)),
# [collections] int, min seconds to wait between checks for
# whether a template needs reloading
auto_reload = int(app_conf.get("evoque.auto_reload", 60)),
# [collections] bool, consume all whitespace trailing a directive
slurpy_directives = app_conf.get("evoque.slurpy_directives")=="true",
# [collections/templates] str or class, to specify the *escaped*
# string class that should be used i.e. if any str input is not of
# this type, then cast it to this type).
# Builtin str key values are: "xml" -> qpy.h8, "str" -> unicode
quoting = app_conf.get("evoque.quoting", "xml"),
# [collections/templates] str, preferred encoding to be tried
# first when decoding template source. Evoque decodes templates
# strings heuristically, i.e. guesses the input encoding.
input_encoding = app_conf.get("evoque.input_encoding", "utf-8"),
# [collections/templates] list of filter functions, each having
# the following signature: filter_func(s:basestring) -> basestring
# The functions will be called, in a left-to-right order, after
# template is rendered. NOTE: not settable from the conf ini.
filters=[]
)
# default template (optional) i.e. what to receive
# when calling domain.get_template() with no params
if app_conf.get("evoque.default_template"):
evoque_domain.get_collection().get_template("",
src=app_conf.get("evoque.default_template"))
# attach evoque domain to app_globals
config['pylons.app_globals'].evoque_domain = evoque_domain
development.ini
The above config load_environment() code may be
customized on a per-deployment basis, by specifying any of the
following parameters under the [app:main]
section of the the deployment's .ini file:
# Evoque Domain : http://evoque.gizmojo.org/ext/pylons/
evoque.default_dir =
evoque.default_template =
evoque.restricted = false
evoque.errors = 3
evoque.cache_size = 0
evoque.auto_reload = 2
evoque.slurpy_directives = true
evoque.quoting = xml
evoque.input_encoding = utf-8
If evoque.default_dir is not set,
then Pylon's first templates folder is used.
The filters parameter (on Domain it only serves as site-wide default)
is not settable in the ini.
For a representative usage example of filters see the
Sub-templates in markdown howto.
logging.getLogger("evoque")
Just like any other logger used in a Pylons application, the
evoque logger may be adjusted via a deployment's
conf ini file.
evoque_site/lib/base.py
from pylons.templating import pylons_globals, cached_template
def render_evoque(template_name, extra_vars=None, cache_key=None,
cache_type=None, cache_expire=None,
collection=None, raw=False, quoting=None):
""" Render a template with Evoque : http://evoque.gizmojo.org/ext/pylons/
Accepts the cache options ``cache_key``, ``cache_type``, and
``cache_expire``.
The remaining options affect how template is located, loaded and rendered:
- template_name: normally this is the collection-root-relative locator for
the template; if template had been previously with location specified
via the src option, then may be any arbitrary string identifier.
- collection: either(None, str, Collection), an existing collection,
None implies the default collection
- raw: bool, render the raw template source
- quoting: either(str, type), sets the quoted-string class to use, None
uses the collection's default, "xml" uses qpy.h8, "str" uses unicode
"""
# Create a render callable for the cache function
def render_template():
# Get the globals
# Note: when running in restricted mode which of these globals are
# to be exposed should be a lot more selective.
pg = pylons_globals()
# Update any extra vars if needed
if extra_vars:
pg.update(extra_vars)
# Grab a template reference
template = pg['app_globals'].evoque_domain.get_template(
template_name, collection=collection, raw=raw, quoting=quoting)
return template.evoque(pg, raw=raw, quoting=quoting)
return cached_template(template_name, render_template, cache_key=cache_key,
cache_type=cache_type, cache_expire=cache_expire)
render = render_evoque
evoque_site/setup.py
install_requires=[
"Pylons>=0.9.7",
...,
"evoque>=0.3"
]
add a controller and template
Let's first add and edit a simple controller
and then add a template just to test:
$ paster controller hello
evoque_site/controllers/hello.py
class HelloController(BaseController):
def index(self):
# Return a rendered template with evoque
c.title = "Hello from evoque!"
return render("template.html")
evoque_site/templates/template.html
<html>
<head><title>evoque + pylons : ${c.title}</title></head>
<style type="text/css">
div.code {
white-space: pre; font-family: monospace; line-height: 1.1em;
padding: 0.6em; margin-bottom: 2em;
border: 1px solid #ccc; background-color: #fafafe;
}
</style>
<body>
<h2>${c.title}</h2>
<h3>template evaluation context</h3>
${inspect()} #[ outputs a <div class="code"/> ]#
</body>
</html>
Define a route for the hello.index() view, and load it
in your web browser.
You should see a simple page that dumps the template evaluation context.