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.
You may also wish to explore the
QuickWikiEvoque
tutorial application, that offers a complete Pylons 0.9.7 + SQLAlchemy 0.5
application that you can downlaod and play with.
Let’s assume we create a site from scratch, let’s call it evoque_site.
When asked, enter the template_engine as follows:
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 from webhelpers.html import literal 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.xml, "str" -> unicode # In a Pylons context we use the webhelpers.html.literal class quoting = app_conf.get("evoque.quoting", literal), # [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 = 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-No-More string class to use, None uses the collection's default, "xml" uses qpy.xml, "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>=${folder.dist["version"]}" ]
add a controller and template
Let’s first add and edit a simple controller
and then add a template just to test:
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> <div class="code">${inspect()}</div> </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.