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
13 app_label, model = model.split('.')
14 self.model = ContentType.objects.get(app_label=app_label, model=model).model_class()
15 self.varname = varname
16 self.object_pk = object_pk
17 self.template_name = template_name
19 def render(self, context):
20 if self.template_name is not None:
21 template_name = self.template_name.resolve(context)
24 t = template.loader.get_template(template_name)
25 except template.TemplateDoesNotExist:
26 return settings.TEMPLATE_STRING_IF_INVALID
28 if self.varname not in context:
29 context[self.varname] = {}
30 context[self.varname][self.model] = t
33 # Otherwise self.object_pk is set. Render the instance with the appropriate template!
35 instance = self.model.objects.get(pk=self.object_pk.resolve(context))
36 except self.model.DoesNotExist:
37 return settings.TEMPLATE_STRING_IF_INVALID
40 t = context[self.varname][self.model]
42 return settings.TEMPLATE_STRING_IF_INVALID
45 context['embedded'] = instance
46 t_rendered = t.render(context)
51 def do_embed(parser, token):
53 The {% embed %} tag can be used in three ways:
54 {% embed as <varname> %} :: This sets which variable will be used to track embedding template names for the current context. Default: "embed"
55 {% embed <app_label>.<model_name> with <template> %} :: Sets which template will be used to render a particular model.
56 {% embed <app_label>.<model_name> <object_pk> %} :: Embeds the instance specified by the given parameters in the document with the previously-specified template.
58 args = token.split_contents()
62 raise template.TemplateSyntaxError('"%s" template tag must have at least three arguments.' % tag)
64 raise template.TemplateSyntaxError('"%s" template tag may have no more than four arguments.' % tag)
66 if len(args) == 3 and args[1] == "as":
67 parser._embedNodeVarName = args[2]
68 return template.defaulttags.CommentNode()
70 if '.' not in args[1]:
71 raise template.TemplateSyntaxError('"%s" template tag expects the first argument to be of the type app_label.model' % tag)
74 return EmbedNode(args[1], object_pk=args[2], varname=getattr(parser, '_embedNodeVarName', 'embed'))
78 raise template.TemplateSyntaxError('"%s" template tag requires the second of three arguments to be "with"' % tag)
80 if args[3][0] not in ['"', "'"] and args[3][-1] not in ['"', "'"]:
81 raise template.TemplateSyntaxError('"%s" template tag expects the template name to be in quotes.' % tag)
82 if args[3][0] != args[3][-1]:
83 raise template.TemplateSyntaxError('"%s" template tag called with non-matching quotes.' % tag)
85 template_name = args[3].strip('"\'')
87 return EmbedNode(args[1], template_name=template_name, varname=getattr(parser, '_embedNodeVarName', 'embed'))
90 register.tag('embed', do_embed)