:members: disable_buffering, enable_buffering, dump
+Autoescaping
+------------
+
+.. versionadded:: 2.4
+
+As of Jinja 2.4 the preferred way to do autoescaping is to enable the
+:ref:`autoescape-extension` and to configure a sensible default for
+autoescaping. This makes it possible to enable and disable autoescaping
+on a per-template basis (HTML versus text for instance).
+
+Here a recommended setup that enables autoescaping for templates ending
+in ``'.html'``, ``'.htm'`` and ``'.xml'`` and disabling it by default
+for all other extensions::
+
+ def guess_autoescape(template_name):
+ if template_name is None or '.' not in template_name:
+ return False
+ ext = template_name.rsplit('.', 1)[1]
+ return ext in ('html', 'htm', 'xml')
+
+ env = Environment(autoescape=guess_autoescape,
+ loader=PackageLoader('mypackage'),
+ extensions=['jinja2.ext.autoescape'])
+
+When implementing a guessing autoescape function, make sure you also
+accept `None` as valid template name. This will be passed when generating
+templates from strings.
+
+Inside the templates the behaviour can be temporarily changed by using
+the `autoescape` block (see :ref:`autoescape-overrides`).
+
+
.. _identifier-naming:
Notes on Identifiers
def visit_Template(self, node, frame=None):
assert frame is None, 'no root frame allowed'
- eval_ctx = EvalContext(self.environment)
+ eval_ctx = EvalContext(self.environment, self.name)
from jinja2.runtime import __all__ as exported
self.writeline('from __future__ import division')
`autoescape`
If set to true the XML/HTML autoescaping feature is enabled by
default. For more details about auto escaping see
- :class:`~jinja2.utils.Markup`.
+ :class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also
+ be a callable that is passed the template name and has to
+ return `True` or `False` depending on autoescape should be
+ enabled by default.
+
+ .. versionchanged:: 2.4
+ `autoescape` can now be a function
`loader`
The template loader for this environment.
to it in extensions.
"""
- def __init__(self, environment):
- self.autoescape = environment.autoescape
+ def __init__(self, environment, template_name=None):
+ if callable(environment.autoescape):
+ self.autoescape = environment.autoescape(template_name)
+ else:
+ self.autoescape = environment.autoescape
self.volatile = False
def save(self):
def __getitem__(self, name):
blocks = self.__context.blocks[name]
- wrap = self.__context.environment.autoescape and \
+ wrap = self.__context.eval_ctx.autoescape and \
Markup or (lambda x: x)
return BlockReference(name, self.__context, blocks, 0)
self.parent = parent
self.vars = {}
self.environment = environment
- self.eval_ctx = EvalContext(self.environment)
+ self.eval_ctx = EvalContext(self.environment, name)
self.exported_vars = set()
self.name = name
@internalcode
def __call__(self):
rv = concat(self._stack[self._depth](self._context))
- if self._context.environment.autoescape:
+ if self._context.eval_ctx.autoescape:
rv = Markup(rv)
return rv
from jinja2 import Environment, Undefined, DebugUndefined, \
StrictUndefined, UndefinedError, Template, meta, \
- is_undefined, Template
+ is_undefined, Template, DictLoader
from jinja2.utils import Cycler
env = Environment()
assert env.get_or_select_template([t]) is t
assert env.get_or_select_template(t) is t
+ def test_autoescape_autoselect(self):
+ def select_autoescape(name):
+ if name is None or '.' not in name:
+ return False
+ return name.endswith('.html')
+ env = Environment(autoescape=select_autoescape,
+ loader=DictLoader({
+ 'test.txt': '{{ foo }}',
+ 'test.html': '{{ foo }}'
+ }))
+ t = env.get_template('test.txt')
+ assert t.render(foo='<foo>') == '<foo>'
+ t = env.get_template('test.html')
+ assert t.render(foo='<foo>') == '<foo>'
+ t = env.from_string('{{ foo }}')
+ assert t.render(foo='<foo>') == '<foo>'
+
class MetaTestCase(JinjaTestCase):