Skip to content

Instantly share code, notes, and snippets.

@gdugas
Last active December 27, 2015 18:39
Show Gist options
  • Save gdugas/7371737 to your computer and use it in GitHub Desktop.
Save gdugas/7371737 to your computer and use it in GitHub Desktop.
Django include tag: include_selected
from django import template
from django.template import Context, loader
from django.template.base import Node, token_kwargs, TemplateSyntaxError
from django.utils import six
from django.conf import settings
register = template.Library()
class IncludeSelectedNode(Node):
def __init__(self, templates, extra_context={}, options={}):
self.templates = templates
self.extra_context = extra_context
self.options = options
options.setdefault('only', False)
options.setdefault('once', False)
def render(self, context):
inc_stack = getattr(context, 'inc_stack', [])
templates = [t.resolve(context) for t in self.templates]
extra_context = {key: value.resolve(context) for key, value in six.iteritems(self.extra_context)}
try:
t = loader.select_template(templates)
if self.options['once'] and t.name in inc_stack:
return ''
inc_stack.append(t.name)
setattr(context, 'inc_stack', inc_stack)
c = Context()
if not self.options['only']:
c.update(context)
c.update(extra_context)
return t.render(c)
except:
if settings.TEMPLATE_DEBUG:
raise
return ''
@register.tag
def include_selected(parser, token):
flags = ['only', 'once']
splitted = token.split_contents()
# tag name poping
splitted.pop(0)
templates = []
while len(splitted) > 0 and not splitted[0] == 'with' and not splitted[0] in flags:
templates.append(parser.compile_filter(splitted.pop(0)))
extra_context = {}
if len(splitted) > 0 and splitted[0] == 'with':
splitted.pop(0)
while len(splitted) > 0 and not splitted[0] in flags:
extra_context = token_kwargs(splitted, parser)
options = {}
while len(splitted) > 0:
flag = splitted.pop()
if not flag in flags:
raise TemplateSyntaxError("Unknown parameter: %s" % flag)
options[flag] = True
return IncludeSelectedNode(templates, extra_context=extra_context, options=options)
@gdugas
Copy link
Author

gdugas commented Nov 8, 2013

Here is a django template tags which allow you to specify multiple templates in case of the firsts does not exists

Syntax

{% include_selected 'my_template1.html' 'my_template2' 'my_template3' %}

with and only

Like include template tag, you can pass additional context to the template and render the context only with the variables provided:

{% include_selected 'my_template1.html' 'my_template2' 'my_template3' with var1='value1' var2=context_var only %}

once

You can also pass the once parameter, which will only include once time the selected template for the current context:

{% include_selected 'my_template1.html' 'my_template2' 'my_template3' %}
{% include_selected 'my_template1.html' 'my_template2' 'my_template3' once %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment