Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #598 -- Added {% include %} template tag. Added docs and unit t…

…ests. Thanks, rjwittams

git-svn-id: http://code.djangoproject.com/svn/django/trunk@1349 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit bedf10a98dfe46dda39e8a20530f7476e7df90ff 1 parent 1ba8bd1
Adrian Holovaty authored November 22, 2005
45  django/core/template/loader.py
@@ -17,7 +17,7 @@
17 17
 # installed, because pkg_resources is necessary to read eggs.
18 18
 
19 19
 from django.core.exceptions import ImproperlyConfigured
20  
-from django.core.template import Template, Context, Node, TemplateDoesNotExist, TemplateSyntaxError, resolve_variable_with_filters, register_tag
  20
+from django.core.template import Template, Context, Node, TemplateDoesNotExist, TemplateSyntaxError, resolve_variable_with_filters, resolve_variable, register_tag
21 21
 from django.conf.settings import TEMPLATE_LOADERS
22 22
 
23 23
 template_source_loaders = []
@@ -160,6 +160,32 @@ def render(self, context):
160 160
                 parent_block.nodelist = block_node.nodelist
161 161
         return compiled_parent.render(context)
162 162
 
  163
+class ConstantIncludeNode(Node):
  164
+    def __init__(self, template_path):
  165
+        try:
  166
+            t = get_template(template_path)
  167
+            self.template = t
  168
+        except:
  169
+            self.template = None
  170
+
  171
+    def render(self, context):
  172
+        if self.template:
  173
+            return self.template.render(context)
  174
+        else:
  175
+            return ''
  176
+
  177
+class IncludeNode(Node):
  178
+    def __init__(self, template_name):
  179
+        self.template_name = template_name
  180
+
  181
+    def render(self, context):
  182
+         try:
  183
+             template_name = resolve_variable(self.template_name, context)
  184
+             t = get_template(template_name)
  185
+             return t.render(context)
  186
+         except:
  187
+             return '' # Fail silently for invalid included templates.
  188
+
163 189
 def do_block(parser, token):
164 190
     """
165 191
     Define a block that can be overridden by child templates.
@@ -202,5 +228,22 @@ def do_extends(parser, token):
202 228
         raise TemplateSyntaxError, "'%s' cannot appear more than once in the same template" % bits[0]
203 229
     return ExtendsNode(nodelist, parent_name, parent_name_var)
204 230
 
  231
+def do_include(parser, token):
  232
+    """
  233
+    Loads a template and renders it with the current context.
  234
+
  235
+    Example::
  236
+
  237
+        {% include "foo/some_include" %}
  238
+    """
  239
+    bits = token.contents.split()
  240
+    if len(bits) != 2:
  241
+        raise TemplateSyntaxError, "%r tag takes one argument: the name of the template to be included" % bits[0]
  242
+    path = bits[1]
  243
+    if path[0] in ('"', "'") and path[-1] == path[0]:
  244
+        return ConstantIncludeNode(path[1:-1])
  245
+    return IncludeNode(bits[1])
  246
+
205 247
 register_tag('block', do_block)
206 248
 register_tag('extends', do_extends)
  249
+register_tag('include', do_include)
36  docs/templates.txt
@@ -492,6 +492,40 @@ ifnotequal
492 492
 
493 493
 Just like ``ifequal``, except it tests that the two arguments are not equal.
494 494
 
  495
+include
  496
+~~~~~~~
  497
+
  498
+**Only available in Django development version.**
  499
+
  500
+Loads a template and renders it with the current context. This is a way of
  501
+"including" other templates within a template.
  502
+
  503
+The template name can either be a variable or a hard-coded (quoted) string,
  504
+in either single or double quotes.
  505
+
  506
+This example includes the contents of the template ``"foo/bar"``::
  507
+
  508
+    {% include "foo/bar" %}
  509
+
  510
+This example includes the contents of the template whose name is contained in
  511
+the variable ``template_name``::
  512
+
  513
+    {% include template_name %}
  514
+
  515
+An included template is rendered with the context of the template that's
  516
+including it. This example produces the output ``"Hello, John"``:
  517
+
  518
+    * Context: variable ``person`` is set to ``"john"``.
  519
+    * Template::
  520
+
  521
+        {% include "name_snippet" %}
  522
+
  523
+    * The ``name_snippet`` template::
  524
+
  525
+        Hello, {{ person }}
  526
+
  527
+See also: ``{% ssi %}``.
  528
+
495 529
 load
496 530
 ~~~~
497 531
 
@@ -645,6 +679,8 @@ file are evaluated as template code, within the current context::
645 679
 Note that if you use ``{% ssi %}``, you'll need to define
646 680
 `ALLOWED_INCLUDE_ROOTS`_ in your Django settings, as a security measure.
647 681
 
  682
+See also: ``{% include %}``.
  683
+
648 684
 .. _ALLOWED_INCLUDE_ROOTS: http://www.djangoproject.com/documentation/settings/#allowed-include-roots
649 685
 
650 686
 templatetag
6  tests/othertests/templates.py
@@ -134,6 +134,12 @@ def method(self):
134 134
     'ifnotequal03': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
135 135
     'ifnotequal04': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 1}, "no"),
136 136
 
  137
+    ### INCLUDE TAG ###########################################################
  138
+    'include01': ('{% include "basic-syntax01" %}', {}, "something cool"),
  139
+    'include02': ('{% include "basic-syntax02" %}', {'headline': 'Included'}, "Included"),
  140
+    'include03': ('{% include template_name %}', {'template_name': 'basic-syntax02', 'headline': 'Included'}, "Included"),
  141
+    'include04': ('a{% include "nonexistent" %}b', {}, "ab"),
  142
+
137 143
     ### INHERITANCE ###########################################################
138 144
 
139 145
     # Standard template with no inheritance

0 notes on commit bedf10a

Please sign in to comment.
Something went wrong with that request. Please try again.