def visit_Block(self, node, frame):
"""Call a block and register it for the template."""
+ level = 1
if frame.toplevel:
# if we know that we are a child template, there is no need to
# check if we are one
if self.has_known_extends:
return
- self.writeline('if parent_root is None:')
- self.indent()
- self.writeline('for event in context.blocks[0][%r](context):' % node.name)
+ if self.extends_so_far > 0:
+ self.writeline('if parent_root is None:')
+ self.indent()
+ level += 1
+ self.writeline('for event in context.blocks[%r][-1](context):' % node.name)
self.indent()
self.writeline('yield event')
- self.outdent(1 + frame.toplevel)
+ self.outdent(level)
def visit_Extends(self, node, frame):
"""Calls the extender."""
raise CompilerExit()
self.outdent()
- self.writeline('parent_root = extends(', node, 1)
+ self.writeline('parent_root = environment.get_template(', node, 1)
self.visit(node.template, frame)
- self.write(', context, environment)')
+ self.write(', %r).root_render_func' % self.filename)
# if this extends statement was in the root level we can take
# advantage of that information and simplify the generated code
return f.read().decode(self.encoding)
finally:
f.close()
+
+
+class DictLoader(BaseLoader):
+
+ def __init__(self, mapping):
+ self.mapping = mapping
+
+ def get_source(self, environment, template):
+ if template in self.mapping:
+ return self.mapping[template], template
+ raise TemplateNotFound(template)
defaultdict = None
-__all__ = ['extends', 'subscribe', 'LoopContext', 'StaticLoopContext',
+__all__ = ['subscribe', 'LoopContext', 'StaticLoopContext',
'TemplateContext', 'Macro', 'Undefined']
-def extends(template_name, context, environment):
- """This loads a template (and evaluates it) and replaces the blocks."""
- template = environment.get_template(template_name, context.filename)
- for name, block in template.blocks.iteritems():
- context.blocks.setdefault(name, []).append(block)
- return template.root_render_func
-
-
def subscribe(obj, argument):
"""Get an item or attribute of an object."""
try:
self.exported = set()
self.filename = filename
self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
- self.stream_muted = False
+ if isinstance(globals, TemplateContext):
+ for name, parent_blocks in globals.blocks.iteritems():
+ self.blocks.setdefault(name, []).extend(parent_blocks)
def __setitem__(self, key, value):
"""If we set items to the dict we track the variables set so
from jinja2 import Environment
+from jinja2.loaders import DictLoader
-env = Environment()
-tmpl = env.from_string("""<!doctype html>
-<html>
- <head>
- <title>{{ page_title|e }}</title>
- </head>
- <body>
- <ul class="navigation">
- {%- for href, caption in [
- ('index.html', 'Index'),
- ('projects.html', 'Projects'),
- ('about.html', 'About')
- ] %}
- <li><a href="{{ href|e }}">{{ caption|e }}</a></li>
- {%- endfor %}
- </ul>
- <div class="body">
- {{ body }}
- </div>
- </body>
-</html>\
-""")
+env = Environment(loader=DictLoader({
+'child.html': u'''\
+{% extends master_layout or 'master.html' %}
+{% macro get_the_answer() %}42{% endmacro %}
+{% block body %}
+ {{ get_the_answer() }}
+{% endblock %}
+''',
+'master.html': u'''\
+<!doctype html>
+<title>Foo</title>
+{% block body %}{% endblock %}
+'''
+}))
-print tmpl.render(page_title='<foo>', body='<p>Hello World</p>')
+tmpl = env.get_template("child.html")
+print tmpl.render()