summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hausknecht <nelson@destiny.(none)>2010-03-09 15:35:37 +0100
committerMarcel Hellkamp <marc@gsites.de>2010-03-09 15:35:37 +0100
commit1f8f5fc458273d4d8608ec3f80b68cc2da24056c (patch)
tree4b921b69ea9451e69cab403063d77c1104b2f273
parent77d5391dedb19459d570edcea71ab78b0c374abe (diff)
downloadbottle-1f8f5fc458273d4d8608ec3f80b68cc2da24056c.tar.gz
Allow passing arguments to the Jinja2 template prepare method.
-rwxr-xr-xbottle.py39
-rw-r--r--test/test_jinja2.py20
2 files changed, 50 insertions, 9 deletions
diff --git a/bottle.py b/bottle.py
index 8d03532..b6f322b 100755
--- a/bottle.py
+++ b/bottle.py
@@ -1272,13 +1272,17 @@ class BaseTemplate(object):
""" Base class and minimal API for template adapters """
extentions = ['tpl','html','thtml','stpl']
- def __init__(self, source=None, name=None, lookup=[], encoding='utf8'):
+ def __init__(self, source=None, name=None, lookup=[], encoding='utf8',
+ filters=None, tests=None):
""" Create a new template.
If the source parameter (str or buffer) is missing, the name argument
is used to guess a template filename. Subclasses can assume that
either self.source or self.filename is set. Both are strings.
The lookup-argument works similar to sys.path for templates.
The encoding parameter is used to decode byte strings or files.
+ The parameters filters and tests are both jinja2 specific. The both
+ contains dicts of the form {'name': function, ...} in order to pass them
+ to jinja2.environment.filters or jinja2.environment..tests.
"""
self.name = name
self.source = source.read() if hasattr(source, 'read') else source
@@ -1291,7 +1295,7 @@ class BaseTemplate(object):
raise TemplateError('Template %s not found.' % repr(name))
if not self.source and not self.filename:
raise TemplateError('No template specified.')
- self.prepare()
+ self.prepare(filters=filters, tests=tests)
@classmethod
def search(cls, name, lookup=[]):
@@ -1324,7 +1328,7 @@ class MakoTemplate(BaseTemplate):
default_filters=None
global_variables={}
- def prepare(self):
+ def prepare(self, **kwargs):
from mako.template import Template
from mako.lookup import TemplateLookup
#TODO: This is a hack... http://github.com/defnull/bottle/issues#issue/8
@@ -1345,7 +1349,7 @@ class MakoTemplate(BaseTemplate):
class CheetahTemplate(BaseTemplate):
- def prepare(self):
+ def prepare(self, **kwargs):
from Cheetah.Template import Template
self.context = threading.local()
self.context.vars = {}
@@ -1364,10 +1368,21 @@ class CheetahTemplate(BaseTemplate):
class Jinja2Template(BaseTemplate):
env = None # hopefully, a Jinja environment is actually thread-safe
prefix = "#"
- def prepare(self):
+ def prepare(self, filters=None, tests=None):
+ """
+ Both parameters are passed through the template function.
+ :param filters: dict with custom filters {"name": function}
+ :param tests: dict with custom tests {"name": function}
+ """
if not self.env:
from jinja2 import Environment, FunctionLoader
- self.env = Environment(line_statement_prefix=self.prefix, loader=FunctionLoader(self.loader))
+ self.env = Environment(line_statement_prefix=self.prefix,
+ loader=FunctionLoader(self.loader)
+ )
+ if filters:
+ self.env.filters.update(filters)
+ if tests:
+ self.env.tests.update(tests)
if self.source:
self.tpl = self.env.from_string(self.source)
else:
@@ -1387,7 +1402,7 @@ class SimpleTemplate(BaseTemplate):
blocks = ('if','elif','else','except','finally','for','while','with','def','class')
dedent_blocks = ('elif', 'else', 'except', 'finally')
- def prepare(self):
+ def prepare(self, **kwargs):
if self.source:
self.code = self.translate(self.source)
self.co = compile(self.code, '<string>', 'exec')
@@ -1518,9 +1533,15 @@ def template(tpl, template_adapter=SimpleTemplate, **args):
lookup = args.get('template_lookup', TEMPLATE_PATH)
if tpl not in TEMPLATES or DEBUG:
if "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:
- TEMPLATES[tpl] = template_adapter(source=tpl, lookup=lookup)
+ TEMPLATES[tpl] = template_adapter(source=tpl, lookup=lookup,
+ filters=args.get('filters'),
+ tests=args.get('tests')
+ )
else:
- TEMPLATES[tpl] = template_adapter(name=tpl, lookup=lookup)
+ TEMPLATES[tpl] = template_adapter(name=tpl, lookup=lookup,
+ filters=args.get('filters'),
+ tests=args.get('tests')
+ )
if not TEMPLATES[tpl]:
abort(500, 'Template (%s) not found' % tpl)
args['abort'] = abort
diff --git a/test/test_jinja2.py b/test/test_jinja2.py
index 985316a..9cdacad 100644
--- a/test/test_jinja2.py
+++ b/test/test_jinja2.py
@@ -1,6 +1,8 @@
+# -*- coding: utf-8 -*-
import unittest
from bottle import Jinja2Template
+
class TestJinja2Template(unittest.TestCase):
def test_string(self):
@@ -31,6 +33,24 @@ class TestJinja2Template(unittest.TestCase):
t = Jinja2Template(name='jinja2_inherit', lookup=['./views/']).render()
self.assertEqual('begin abc end', ''.join(t))
+ def test_custom_filters(self):
+ """Templates: jinja2 custom filters """
+ from bottle import jinja2_template as template
+ filters = {"star": lambda var: u"".join((u'*', var, u'*'))}
+ res = template("start {{var|star}} end", var="var", filters=filters)
+ self.assertEqual("start *var* end", res)
+
+ def test_custom_tests(self):
+ """Templates: jinja2 custom tests """
+ from bottle import jinja2_template as template
+ TEMPL = u"""{% if var is even %}gerade{% else %}ungerade{% endif %}"""
+ tests={"even": lambda x: False if x % 2 else True}
+ res = template(TEMPL, var=2, tests=tests)
+ self.assertEqual("gerade", res)
+ res = template(TEMPL, var=1, tests=tests)
+ self.assertEqual("ungerade", res)
+
+
try:
import jinja2
except ImportError: