1 from django import template
2 from django.contrib.contenttypes.models import ContentType
3 from django.conf import settings
6 register = template.Library()
9 class EmbedNode(template.Node):
10 def __init__(self, model, varname, object_pk=None, template_name=None):
11 assert template_name is not None or object_pk is not None
12 app_label, model = model.split('.')
13 self.model = ContentType.objects.get(app_label=app_label, model=model).model_class()
14 self.varname = varname
15 self.object_pk = object_pk
16 self.template_name = template_name
18 def render(self, context):
19 if self.template_name is not None:
20 template_name = self.template_name.resolve(context)
23 t = template.loader.get_template(template_name)
24 except template.TemplateDoesNotExist:
25 return settings.TEMPLATE_STRING_IF_INVALID
27 if self.varname not in context:
28 context[self.varname] = {}
29 context[self.varname][self.model] = t
32 # Otherwise self.object_pk is set. Render the instance with the appropriate template!
34 instance = self.model.objects.get(pk=self.object_pk.resolve(context))
35 except self.model.DoesNotExist:
36 return settings.TEMPLATE_STRING_IF_INVALID
39 t = context[self.varname][self.model]
41 return settings.TEMPLATE_STRING_IF_INVALID
44 context['embedded'] = instance
45 t_rendered = t.render(context)
50 def do_embed(parser, token):
52 The {% embed %} tag can be used in three ways:
53 {% embed as <varname> %} :: This sets which variable will be used to track embedding template names for the current context. Default: "embed"
54 {% embed <app_label>.<model_name> with <template> %} :: Sets which template will be used to render a particular model.
55 {% embed <app_label>.<model_name> <object_pk> %} :: Embeds the instance specified by the given parameters in the document with the previously-specified template.
57 args = token.split_contents()
61 raise template.TemplateSyntaxError('"%s" template tag must have at least three arguments.' % tag)
63 raise template.TemplateSyntaxError('"%s" template tag may have no more than four arguments.' % tag)
65 if len(args) == 3 and args[1] == "as":
66 parser._embedNodeVarName = args[2]
67 return template.defaulttags.CommentNode()
69 if '.' not in args[1]:
70 raise template.TemplateSyntaxError('"%s" template tag expects the first argument to be of the type app_label.model' % tag)
73 return EmbedNode(args[1], object_pk=args[2], varname=getattr(parser, '_embedNodeVarName', 'embed'))
77 raise template.TemplateSyntaxError('"%s" template tag requires the second of three arguments to be "with"' % tag)
79 if args[3][0] not in ['"', "'"] and args[3][-1] not in ['"', "'"]:
80 raise template.TemplateSyntaxError('"%s" template tag expects the template name to be in quotes.' % tag)
81 if args[3][0] != args[3][-1]:
82 raise template.TemplateSyntaxError('"%s" template tag called with non-matching quotes.' % tag)
84 template_name = args[3].strip('"\'')
86 return EmbedNode(args[1], template_name=template_name, varname=getattr(parser, '_embedNodeVarName', 'embed'))
89 register.tag('embed', do_embed)