Skip to content

Instantly share code, notes, and snippets.

@joncotton
Last active October 2, 2015 14:08
Show Gist options
  • Select an option

  • Save joncotton/2255481 to your computer and use it in GitHub Desktop.

Select an option

Save joncotton/2255481 to your computer and use it in GitHub Desktop.
render_model with
"""
A working `render_model with` that works like Django's include templatetag. It's a gist because it's not official enough to fork&commit. There are no tests and `with` isn't implemented on the other `render` tags.
"""
from django.conf import settings
from django.template.loader_tags import BaseIncludeNode
from django.template.defaulttags import token_kwargs
# class RenderObjectNode(template.Node):
# def __init__(self, object, name):
# self.object = template.Variable(object)
# self.name = template.Variable(name)
# def render(self, context):
# name = self.name.resolve(context)
# object = self.object.resolve(context)
# return render_model(object, name, dictionary={},
# context_instance=context)
class RenderObjectNode(BaseIncludeNode):
def __init__(self, obj, template_name, *args, **kwargs):
super(RenderObjectNode, self).__init__(*args, **kwargs)
self.obj = template.Variable(obj)
self.template_name = template.Variable(template_name)
def render_template(self, obj, template_name, context):
values = dict([(name, var.resolve(context)) for name, var
in self.extra_context.iteritems()])
if self.isolated_context:
return render_model(obj, template_name, context_instance=context.new(values))
context.update(values)
output = render_model(obj, template_name, context_instance=context)
context.pop()
return output
def render(self, context):
try:
obj = self.obj.resolve(context)
template_name = self.template_name.resolve(context)
return self.render_template(obj, template_name, context)
except:
if settings.TEMPLATE_DEBUG:
raise
return ''
# @register.tag(name="render_model")
# def do_render_model(parser, token):
# tokens = token.split_contents()
# if len(tokens) is 3:
# _, object, name = tokens
# return RenderObjectNode(object, name)
# message = "Too %s parameters" % ("many" if len(tokens) > 3 else "few")
# raise TemplateSyntaxError(message)
@register.tag(name="render_model")
def do_render_model(parser, token):
bits = token.split_contents()
if len(bits) < 3:
raise TemplateSyntaxError("%r tag takes at least two arguments: the object and the name of the template to render it with." % bits[0])
options = {}
remaining_bits = bits[3:]
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', {})
# path = bits[2]
# if path[0] in ('"', "'") and path[-1] == path[0]:
# return ConstantIncludeNode(path[1:-1], extra_context=namemap,
# isolated_context=isolated_context)
return RenderObjectNode(bits[1], bits[2], 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