Created
August 11, 2012 14:00
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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