1
"""Render functions and helpers
3
Render functions and helpers
4
============================
6
:mod:`pylons.templating` includes several basic render functions,
7
:func:`render_mako`, :func:`render_genshi` and :func:`render_jinja2`
8
that render templates from the file-system with the assumption that
9
variables intended for the will be attached to :data:`tmpl_context`
10
(hereafter referred to by its short name of :data:`c` which it is
13
The default render functions work with the template language loader
14
object that is setup on the :data:`app_globals` object in the project's
15
:file:`config/environment.py`.
20
Generally, one of the render functions will be imported in the
21
controller. Variables intended for the template are attached to the
22
:data:`c` object. The render functions return unicode (they actually
23
return :class:`~webhelpers.html.literal` objects, a subclass of
28
:data:`tmpl_context` (template context) is abbreviated to :data:`c`
29
instead of its full name since it will likely be used extensively
30
and it's much faster to use :data:`c`. Of course, for users that
31
can't tolerate one-letter variables, feel free to not import
32
:data:`tmpl_context` as :data:`c` since both names are available in
35
Example of rendering a template with some variables::
37
from pylons import tmpl_context as c
38
from pylons.templating import render_mako as render
40
from sampleproject.lib.base import BaseController
42
class SampleController(BaseController):
47
return render('/some/template.mako')
49
And the accompanying Mako template:
53
Hello ${c.first name}, I see your lastname is ${c.last_name}!
55
Your controller will have additional default imports for commonly used
61
Templates rendered in Pylons should include the default Pylons globals
62
as the :func:`render_mako`, :func:`render_genshi` and
63
:func:`render_jinja2` functions. The full list of Pylons globals that
64
are included in the template's namespace are:
66
- :term:`c` -- Template context object
67
- :term:`tmpl_context` -- Template context object
68
- :data:`config` -- Pylons :class:`~pylons.configuration.PylonsConfig`
69
object (acts as a dict)
70
- :term:`app_globals` -- Project application globals object
71
- :term:`h` -- Project helpers module reference
72
- :data:`request` -- Pylons :class:`~pylons.controllers.util.Request`
73
object for this request
74
- :data:`response` -- Pylons :class:`~pylons.controllers.util.Response`
75
object for this request
76
- :class:`session` -- Pylons session object (unless Sessions are
78
- :class:`url <routes.util.URLGenerator>` -- Routes url generator
80
- :class:`translator` -- Gettext translator object configured for
82
- :func:`ungettext` -- Unicode capable version of gettext's ngettext
83
function (handles plural translations)
84
- :func:`_` -- Unicode capable gettext translate function
85
- :func:`N_` -- gettext no-op function to mark a string for
86
translation, but doesn't actually translate
88
Configuring the template language
89
---------------------------------
91
The template engine is created in the projects
92
``config/environment.py`` and attached to the ``app_globals`` (g)
93
instance. Configuration options can be directly passed into the
94
template engine, and are used by the render functions.
98
Don't change the variable name on :data:`app_globals` that the
99
template loader is attached to if you want to use the render_*
100
functions that :mod:`pylons.templating` comes with. The render_*
101
functions look for the template loader to render the template.
106
from webhelpers.html import literal
110
__all__ = ['render_genshi', 'render_jinja2', 'render_mako', 'render_response']
112
PYLONS_VARS = ['c', 'app_globals', 'config', 'h', 'render', 'request',
113
'session', 'translator', 'ungettext', '_', 'N_']
115
log = logging.getLogger(__name__)
118
"""Create and return a dictionary of global Pylons variables
120
Render functions should call this to retrieve a list of global
121
Pylons variables that should be included in the global template
122
namespace if possible.
124
Pylons variables that are returned in the dictionary:
125
``c``, ``h``, ``_``, ``N_``, config, request, response,
126
translator, ungettext, ``url``
128
If SessionMiddleware is being used, ``session`` will also be
129
available in the template namespace.
132
conf = pylons.config._current_obj()
133
c = pylons.tmpl_context._current_obj()
134
app_globals = conf.get('pylons.app_globals')
139
app_globals=app_globals,
140
h=conf.get('pylons.h'),
141
request=pylons.request._current_obj(),
142
response=pylons.response._current_obj(),
143
url=pylons.url._current_obj(),
144
translator=pylons.translator._current_obj(),
145
ungettext=pylons.i18n.ungettext,
150
# If the session was overriden to be None, don't populate the session
152
econf = pylons.config['pylons.environ_config']
153
if 'beaker.session' in pylons.request.environ or \
154
('session' in econf and econf['session'] in pylons.request.environ):
155
pylons_vars['session'] = pylons.session._current_obj()
156
log.debug("Created render namespace with pylons vars: %s", pylons_vars)
160
def cached_template(template_name, render_func, ns_options=(),
161
cache_key=None, cache_type=None, cache_expire=None,
163
"""Cache and render a template
165
Cache a template to the namespace ``template_name``, along with a
166
specific key if provided.
171
Name of the template, which is used as the template namespace.
173
Function used to generate the template should it no longer be
174
valid or doesn't exist in the cache.
176
Tuple of strings, that should correspond to keys likely to be
177
in the ``kwargs`` that should be used to construct the
178
namespace used for the cache. For example, if the template
179
language supports the 'fragment' option, the namespace should
180
include it so that the cached copy for a template is not the
181
same as the fragment version of it.
183
Caching options (uses Beaker caching middleware)
186
Key to cache this copy of the template under.
188
Valid options are ``dbm``, ``file``, ``memory``, ``database``,
191
Time in seconds to cache this template with this ``cache_key``
192
for. Or use 'never' to designate that the cache should never
195
The minimum key required to trigger caching is
196
``cache_expire='never'`` which will cache the template forever
200
# If one of them is not None then the user did set something
201
if cache_key is not None or cache_expire is not None or cache_type \
207
cache_key = 'default'
208
if cache_expire == 'never':
210
namespace = template_name
211
for name in ns_options:
212
namespace += str(kwargs.get(name))
213
cache = pylons.cache.get_cache(namespace, type=cache_type)
214
content = cache.get_value(cache_key, createfunc=render_func,
215
expiretime=cache_expire)
221
def render_mako(template_name, extra_vars=None, cache_key=None,
222
cache_type=None, cache_expire=None):
223
"""Render a template with Mako
225
Accepts the cache options ``cache_key``, ``cache_type``, and
229
# Create a render callable for the cache function
230
def render_template():
231
# Pull in extra vars if needed
232
globs = extra_vars or {}
234
# Second, get the globals
235
globs.update(pylons_globals())
237
# Grab a template reference
238
template = globs['app_globals'].mako_lookup.get_template(template_name)
240
return literal(template.render_unicode(**globs))
242
return cached_template(template_name, render_template, cache_key=cache_key,
243
cache_type=cache_type, cache_expire=cache_expire)
246
def render_mako_def(template_name, def_name, cache_key=None,
247
cache_type=None, cache_expire=None, **kwargs):
248
"""Render a def block within a Mako template
250
Takes the template name, and the name of the def within it to call.
251
If the def takes arguments, they should be passed in as keyword
256
# To call the def 'header' within the 'layout.mako' template
257
# with a title argument
258
render_mako_def('layout.mako', 'header', title='Testing')
260
Also accepts the cache options ``cache_key``, ``cache_type``, and
264
# Create a render callable for the cache function
265
def render_template():
266
# Pull in extra vars if needed
269
# Second, get the globals
270
globs.update(pylons_globals())
272
# Grab a template reference
273
template = globs['app_globals'].mako_lookup.get_template(
274
template_name).get_def(def_name)
276
return literal(template.render_unicode(**globs))
278
return cached_template(template_name, render_template, cache_key=cache_key,
279
cache_type=cache_type, cache_expire=cache_expire)
282
def render_genshi(template_name, extra_vars=None, cache_key=None,
283
cache_type=None, cache_expire=None, method='xhtml'):
284
"""Render a template with Genshi
286
Accepts the cache options ``cache_key``, ``cache_type``, and
287
``cache_expire`` in addition to method which are passed to Genshi's
291
# Create a render callable for the cache function
292
def render_template():
293
# Pull in extra vars if needed
294
globs = extra_vars or {}
296
# Second, get the globals
297
globs.update(pylons_globals())
299
# Grab a template reference
300
template = globs['app_globals'].genshi_loader.load(template_name)
302
return literal(template.generate(**globs).render(method=method,
305
return cached_template(template_name, render_template, cache_key=cache_key,
306
cache_type=cache_type, cache_expire=cache_expire,
307
ns_options=('method'), method=method)
310
def render_jinja2(template_name, extra_vars=None, cache_key=None,
311
cache_type=None, cache_expire=None):
312
"""Render a template with Jinja2
314
Accepts the cache options ``cache_key``, ``cache_type``, and
318
# Create a render callable for the cache function
319
def render_template():
320
# Pull in extra vars if needed
321
globs = extra_vars or {}
323
# Second, get the globals
324
globs.update(pylons_globals())
326
# Grab a template reference
328
globs['app_globals'].jinja2_env.get_template(template_name)
330
return literal(template.render(**globs))
332
return cached_template(template_name, render_template, cache_key=cache_key,
333
cache_type=cache_type, cache_expire=cache_expire)