Skip to content

Instantly share code, notes, and snippets.

@public
Created December 14, 2016 14:03
Show Gist options
  • Save public/79b7d489123864f65663925dc5bdba87 to your computer and use it in GitHub Desktop.
Save public/79b7d489123864f65663925dc5bdba87 to your computer and use it in GitHub Desktop.
from __future__ import absolute_import
from django.conf import settings
from django.template import Library, engines
from django.template.base import Node, TemplateSyntaxError, token_kwargs
import six
register = Library()
class Jinja2IncludeNode(Node):
"""
Import a Jinja2 template into a DTL template.
"""
def __init__(self, template, *args, **kwargs):
self.template = template
self.extra_context = kwargs.pop('extra_context', None)
self.isolated_context = kwargs.pop('isolated_context', False)
super(Jinja2IncludeNode, self).__init__(*args, **kwargs)
def render(self, context):
try:
engine = engines['jinja2']
template = self.template.resolve(context)
# Does this quack like a Template?
if not callable(getattr(template, 'render', None)):
# If not, we'll try get_template
template = engine.get_template(template)
values = {
name: var.resolve(context)
for name, var in six.iteritems(self.extra_context)
}
if self.isolated_context:
return template.render(context.new(values))
with context.push(**values):
return template.render(context.flatten())
except Exception:
if settings.DEBUG:
raise
return ''
@register.tag('jinja2_include')
def do_jinja2_include(parser, token):
"""
Loads a Jinja2 template and renders it with the current context.
You can pass additional context using keyword arguments.
e.g.
{% jinja2_include 'foo/include' %}
{% jinja2_include 'foo/include' bar="foop" %}
"""
bits = token.split_contents()
if len(bits) < 2:
raise TemplateSyntaxError(
"%r tag takes at least one argument: the name of the template to "
"be included." % bits[0]
)
options = {}
remaining_bits = bits[2:]
while remaining_bits:
option = remaining_bits.pop(0)
if option in options:
raise TemplateSyntaxError('The %r option was specified more '
'than once.' % option)
if option == 'with':
value = token_kwargs(remaining_bits, parser, support_legacy=False)
if not value:
raise TemplateSyntaxError('"with" in %r tag needs at least '
'one keyword argument.' % bits[0])
elif option == 'only':
value = True
else:
raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
(bits[0], option))
options[option] = value
isolated_context = options.get('only', False)
namemap = options.get('with', {})
return Jinja2IncludeNode(parser.compile_filter(bits[1]), extra_context=namemap,
isolated_context=isolated_context)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment