register = template.Library()
-class EmbedNode(template.Node):
+class ConstantEmbedNode(template.Node):
+ """Analogous to the ConstantIncludeNode, this node precompiles several variables necessary for correct rendering - namely the referenced instance or the included template."""
def __init__(self, content_type, varname, object_pk=None, template_name=None, kwargs=None):
assert template_name is not None or object_pk is not None
self.content_type = content_type
self.kwargs = kwargs
if object_pk is not None:
- self.object_pk = object_pk
- try:
- self.instance = content_type.get_object_for_this_type(pk=object_pk)
- except content_type.model_class().DoesNotExist:
- self.instance = False
+ self.compile_instance(object_pk)
+ if self.instance is False and settings.TEMPLATE_DEBUG:
+ raise
else:
self.instance = None
if template_name is not None:
- try:
- self.template = template.loader.get_template(template_name)
- except template.TemplateDoesNotExist:
- self.template = False
+ self.compile_template(template_name[1:-1])
+ if self.template is False and settings.TEMPLATE_DEBUG:
+ raise
else:
self.template = None
+ def compile_instance(self, object_pk):
+ self.object_pk = object_pk
+ model = self.content_type.model_class()
+ try:
+ self.instance = model.objects.get(pk=object_pk)
+ except model.DoesNotExist:
+ self.instance = False
+
+ def compile_template(self, template_name):
+ try:
+ self.template = template.loader.get_template(template_name)
+ except template.TemplateDoesNotExist:
+ self.template = False
+
def render(self, context):
- if self.template_name is not None:
+ if self.template is not None:
if self.template is False:
return settings.TEMPLATE_STRING_IF_INVALID
if self.instance is None or self.instance is False:
return settings.TEMPLATE_STRING_IF_INVALID
+ return self.render_template(context, self.instance)
+
+ def render_template(self, context, instance):
try:
t = context[self.varname][self.content_type]
except KeyError:
return settings.TEMPLATE_STRING_IF_INVALID
context.push()
- context['embedded'] = self.instance
+ context['embedded'] = instance
+ kwargs = {}
for k, v in self.kwargs.items():
- self.kwargs[k] = v.resolve(context)
- context.update(self.kwargs)
+ kwargs[k] = v.resolve(context)
+ context.update(kwargs)
t_rendered = t.render(context)
context.pop()
return t_rendered
+class EmbedNode(ConstantEmbedNode):
+ def __init__(self, content_type, varname, object_pk=None, template_name=None, kwargs=None):
+ assert template_name is not None or object_pk is not None
+ self.content_type = content_type
+ self.varname = varname
+
+ kwargs = kwargs or {}
+ for k, v in kwargs.items():
+ kwargs[k] = template.Variable(v)
+ self.kwargs = kwargs
+
+ if object_pk is not None:
+ self.object_pk = template.Variable(object_pk)
+ else:
+ self.object_pk = None
+ self.instance = None
+
+ if template_name is not None:
+ self.template_name = template.Variable(template_name)
+ else:
+ self.template_name = None
+ self.template = None
+
+ def render(self, context):
+ if self.template_name is not None:
+ template_name = self.template_name.resolve(context)
+ self.compile_template(template_name)
+
+ if self.object_pk is not None:
+ object_pk = self.object_pk.resolve(context)
+ self.compile_instance(object_pk)
+
+ return super(EmbedNode, self).render(context)
+
+
def get_embedded(self):
- return template.loader.get_template(self.template_name)
+ return self.template
-setattr(EmbedNode, LOADED_TEMPLATE_ATTR, property(get_embedded))
+setattr(ConstantEmbedNode, LOADED_TEMPLATE_ATTR, property(get_embedded))
def do_embed(parser, token):
except ContentType.DoesNotExist:
raise template.TemplateSyntaxError('"%s" template tag option "references" requires an argument of the form app_label.model which refers to an installed content type (see django.contrib.contenttypes)' % tag)
+ varname = getattr(parser, '_embedNodeVarName', 'embed')
+
if args[2] == "with":
if len(args) > 4:
raise template.TemplateSyntaxError('"%s" template tag may have no more than four arguments.' % tag)
- if args[3][0] not in ['"', "'"] and args[3][-1] not in ['"', "'"]:
- raise template.TemplateSyntaxError('"%s" template tag expects the template name to be in quotes.' % tag)
- if args[3][0] != args[3][-1]:
- raise template.TemplateSyntaxError('"%s" template tag called with non-matching quotes.' % tag)
+ if args[3][0] in ['"', "'"] and args[3][0] == args[3][-1]:
+ return ConstantEmbedNode(ct, template_name=args[3], varname=varname)
- template_name = args[3].strip('"\'')
-
- return EmbedNode(ct, template_name=template_name, varname=getattr(parser, '_embedNodeVarName', 'embed'))
- object_pk = args[2]
- varname = getattr(parser, '_embedNodeVarName', 'embed')
+ return EmbedNode(ct, template_name=args[3], varname=varname)
+ object_pk = args[2]
remaining_args = args[3:]
kwargs = {}
for arg in remaining_args: