Browse Source

Started working on refactoring Jinja integration

pull/112/head
Armin Ronacher 15 years ago
parent
commit
7599046d04
  1. 4
      CHANGES
  2. 7
      docs/quickstart.rst
  3. 42
      flask.py
  4. 8
      tests/flask_tests.py
  5. 1
      tests/templates/mail.txt

4
CHANGES

@ -11,6 +11,10 @@ Codename to be decided, release date to be announced.
- fixed a bug with subdomains that was caused by the inability to - fixed a bug with subdomains that was caused by the inability to
specify the server name. The server name can now be set with specify the server name. The server name can now be set with
the `SERVER_NAME` config key. the `SERVER_NAME` config key.
- autoescaping is no longer active for all templates. Instead it
is only active for ``.html``, ``.htm``, ``.xml`` and ``.xhtml``.
Inside templates this behaviour can be changed with the
``autoescape`` tag.
Version 0.4 Version 0.4
----------- -----------

7
docs/quickstart.rst

@ -414,6 +414,13 @@ Markup(u'<blink>hacker</blink>')
>>> Markup('<em>Marked up</em> &raquo; HTML').striptags() >>> Markup('<em>Marked up</em> &raquo; HTML').striptags()
u'Marked up \xbb HTML' u'Marked up \xbb HTML'
.. versionchanged:: 0.5
Autoescaping is no longer enabled for all templates. The following
extensions for templates trigger autoescaping: ``.html``, ``.htm``,
``.xml``, ``.xhtml``. Templates loaded from string will have
autoescaping disabled.
.. [#] Unsure what that :class:`~flask.g` object is? It's something you .. [#] Unsure what that :class:`~flask.g` object is? It's something you
can store information on yourself, check the documentation of that can store information on yourself, check the documentation of that
object (:class:`~flask.g`) and the :ref:`sqlite3` for more object (:class:`~flask.g`) and the :ref:`sqlite3` for more

42
flask.py

@ -788,6 +788,15 @@ class Config(dict):
return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self)) return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self))
def _select_autoescape(filename):
"""Returns `True` if autoescaping should be active for the given
template name.
"""
if filename is None:
return False
return filename.endswith(('.html', '.htm', '.xml', '.xhtml'))
class Flask(_PackageBoundObject): class Flask(_PackageBoundObject):
"""The flask object implements a WSGI application and acts as the central """The flask object implements a WSGI application and acts as the central
object. It is passed the name of the module or package of the object. It is passed the name of the module or package of the
@ -920,7 +929,7 @@ class Flask(_PackageBoundObject):
#: Options that are passed directly to the Jinja2 environment. #: Options that are passed directly to the Jinja2 environment.
jinja_options = ImmutableDict( jinja_options = ImmutableDict(
autoescape=True, autoescape=_select_autoescape,
extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'] extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_']
) )
@ -1018,13 +1027,8 @@ class Flask(_PackageBoundObject):
#: The Jinja2 environment. It is created from the #: The Jinja2 environment. It is created from the
#: :attr:`jinja_options` and the loader that is returned #: :attr:`jinja_options` and the loader that is returned
#: by the :meth:`create_jinja_loader` function. #: by the :meth:`create_jinja_loader` function.
self.jinja_env = Environment(loader=self.create_jinja_loader(), self.jinja_env = self.create_jinja_environment()
**self.jinja_options) self.init_jinja_globals()
self.jinja_env.globals.update(
url_for=url_for,
get_flashed_messages=get_flashed_messages
)
self.jinja_env.filters['tojson'] = _tojson_filter
@property @property
def logger(self): def logger(self):
@ -1061,6 +1065,15 @@ class Flask(_PackageBoundObject):
self._logger = logger self._logger = logger
return logger return logger
def create_jinja_environment(self):
"""Creates the Jinja2 environment based on :attr:`jinja_options`
and :meth:`create_jinja_loader`.
.. versionadded:: 0.5
"""
return Environment(loader=self.create_jinja_loader(),
**self.jinja_options)
def create_jinja_loader(self): def create_jinja_loader(self):
"""Creates the Jinja loader. By default just a package loader for """Creates the Jinja loader. By default just a package loader for
the configured package is returned that looks up templates in the the configured package is returned that looks up templates in the
@ -1071,6 +1084,19 @@ class Flask(_PackageBoundObject):
return FileSystemLoader(os.path.join(self.root_path, 'templates')) return FileSystemLoader(os.path.join(self.root_path, 'templates'))
return PackageLoader(self.import_name) return PackageLoader(self.import_name)
def init_jinja_globals(self):
"""Callde directly after the environment was created to inject
some defaults (like `url_for`, `get_flashed_messages` and the
`tojson` filter.
.. versionadded:: 0.5
"""
self.jinja_env.globals.update(
url_for=url_for,
get_flashed_messages=get_flashed_messages
)
self.jinja_env.filters['tojson'] = _tojson_filter
def update_template_context(self, context): def update_template_context(self, context):
"""Update the template context with some commonly used variables. """Update the template context with some commonly used variables.
This injects request, session and g into the template context. This injects request, session and g into the template context.

8
tests/flask_tests.py

@ -461,6 +461,14 @@ class TemplatingTestCase(unittest.TestCase):
'<p>Hello World!' '<p>Hello World!'
] ]
def test_no_escaping(self):
app = flask.Flask(__name__)
with app.test_request_context():
assert flask.render_template_string('{{ foo }}',
foo='<test>') == '<test>'
assert flask.render_template('mail.txt', foo='<test>') \
== '<test> Mail'
def test_macros(self): def test_macros(self):
app = flask.Flask(__name__) app = flask.Flask(__name__)
with app.test_request_context(): with app.test_request_context():

1
tests/templates/mail.txt

@ -0,0 +1 @@
{{ foo}} Mail
Loading…
Cancel
Save