Skip to content

Instantly share code, notes, and snippets.

@cborgolte
Created August 11, 2012 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cborgolte/3324685 to your computer and use it in GitHub Desktop.
Save cborgolte/3324685 to your computer and use it in GitHub Desktop.
include_as tag for Django templates. Renderd string will be saved in a variable.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
include_as.py - extended include tag for django templates.
Provides the 'as' option when including a template inside a template.
If this option is used, the rendered content is saved to the variable given
after the 'as' statement.
Code mostly copied from the original django include tag implementation.
"""
from django.template.base import TemplateSyntaxError, Library, token_kwargs
from django.template.loader_tags import IncludeNode, ConstantIncludeNode
register = Library()
class ConstantIncludeAsNode(ConstantIncludeNode):
"""Node for the include_as template tag."""
def __init__(self, *args, **kwargs):
self.asvar = kwargs.pop('asvar', None)
super(ConstantIncludeAsNode, self).__init__(*args, **kwargs)
def render(self, context):
value = super(ConstantIncludeAsNode, self).render(context)
if self.asvar:
context[self.asvar] = value
return ''
else:
return value
class IncludeAsNode(IncludeNode):
"""Node for the include_as template tag."""
def __init__(self, *args, **kwargs):
self.asvar = kwargs.pop('asvar', None)
super(IncludeAsNode, self).__init__(*args, **kwargs)
def render(self, context):
value = super(IncludeAsNode, self).render(context)
if self.asvar:
context[self.asvar] = value
return ''
else:
return value
@register.tag('include_as')
def do_include(parser, token):
"""
Works exactly like the buildin 'include' tag.
With the addition that instead of rendering the included template in place,
the rendered text can be stored to a variable.
Example::
{% include "foo/some_include" %} behaves like the buildin include tag
{% include "foo/some_include" as result %} saves rendered content to variable 'result'
"""
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:]
print "INCLUDE:", bits
asvar = None
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
elif option == 'as':
if len(remaining_bits) != 1:
raise TemplateSyntaxError('"as" needs exactly one argument as variable name '
'for storing the rendered template')
asvar = remaining_bits.pop(0)
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', {})
path = bits[1]
if path[0] in ('"', "'") and path[-1] == path[0]:
return ConstantIncludeAsNode(path[1:-1], extra_context=namemap, isolated_context=isolated_context,
asvar=asvar)
return IncludeAsNode(parser.compile_filter(bits[1]), extra_context=namemap,
isolated_context=isolated_context, asvar=asvar)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment