Ticket #7817: 7817.diff

File 7817.diff, 6.7 KB (added by Chris Beaven, 14 years ago)
  • django/template/loader_tags.py

    diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py
    index b8bc741..25dd07d 100644
    a b  
    11from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable
    22from django.template import Library, Node, TextNode
     3from django.template.defaulttags import kwarg_re
    34from django.template.loader import get_template
    45from django.conf import settings
    56from django.utils.safestring import mark_safe
    class ExtendsNode(Node):  
    124125        # the same.
    125126        return compiled_parent._render(context)
    126127
    127 class ConstantIncludeNode(Node):
    128     def __init__(self, template_path):
     128class BaseIncludeNode(Node):
     129    def __init__(self, *args, **kwargs):
     130        self.extra_context = kwargs.pop('extra_context', {})
     131        super(BaseIncludeNode, self).__init__(*args, **kwargs)
     132
     133    def render_template(self, template, context):
     134        values = [(name, var.resolve(context)) for name, var
     135                  in self.extra_context.iteritems()]
     136        context.update(dict(values))
     137        output = template.render(context)
     138        context.pop()
     139        return output
     140
     141class ConstantIncludeNode(BaseIncludeNode):
     142    def __init__(self, template_path, *args, **kwargs):
     143        super(ConstantIncludeNode, self).__init__(*args, **kwargs)
    129144        try:
    130145            t = get_template(template_path)
    131146            self.template = t
    class ConstantIncludeNode(Node):  
    135150            self.template = None
    136151
    137152    def render(self, context):
    138         if self.template:
    139             return self.template.render(context)
    140         else:
     153        if not self.template:
    141154            return ''
     155        return self.render_template(self.template, context)
    142156
    143 class IncludeNode(Node):
    144     def __init__(self, template_name):
    145         self.template_name = Variable(template_name)
     157class IncludeNode(BaseIncludeNode):
     158    def __init__(self, template_name, extra_context={}):
     159        self.template_name = template_name
     160        self.extra_context = extra_context
    146161
    147162    def render(self, context):
    148163        try:
    149164            template_name = self.template_name.resolve(context)
    150             t = get_template(template_name)
    151             return t.render(context)
    152         except TemplateSyntaxError, e:
     165            template = get_template(template_name)
     166            return self.render_template(template, context)
     167        except TemplateSyntaxError:
    153168            if settings.TEMPLATE_DEBUG:
    154169                raise
    155170            return ''
    def do_extends(parser, token):  
    201216
    202217def do_include(parser, token):
    203218    """
    204     Loads a template and renders it with the current context.
     219    Loads a template and renders it with the current context. You can pass
     220    additional context using keyword arguments.
    205221
    206222    Example::
    207223
    208224        {% include "foo/some_include" %}
     225        {% include "foo/some_include" with bar="BAZZ!" baz="BING!" %}
     226
    209227    """
    210228    bits = token.split_contents()
    211     if len(bits) != 2:
    212         raise TemplateSyntaxError("%r tag takes one argument: the name of the template to be included" % bits[0])
     229    if len(bits) < 2:
     230        raise TemplateSyntaxError("%r tag takes at least one argument: the name of the template to be included." % bits[0])
     231    namemap = {}
     232    if len(bits) > 2:
     233        if bits[2] != 'with':
     234            raise TemplateSyntaxError('''Invalid option %r for %r tag.''' % (bits[2], bits[0]))
     235        for bit in bits[3:]:
     236            match = kwarg_re.match(bit)
     237            if not match:
     238                raise TemplateSyntaxError("Malformed arguments to %r tag." % bits[0])
     239            name, value = match.groups()
     240            if not name:
     241                raise TemplateSyntaxError('''"with" part of %r tag accepts only keyword arguments.''' % bits[0])
     242            if name in namemap:
     243                raise TemplateSyntaxError("Tried to bind value to name %r more than once." % name)
     244            namemap[name] = parser.compile_filter(value)
     245        if not namemap:
     246            raise TemplateSyntaxError('''"with" in %r tag needs at least one keyword argument.''' % bits[0])
    213247    path = bits[1]
    214248    if path[0] in ('"', "'") and path[-1] == path[0]:
    215         return ConstantIncludeNode(path[1:-1])
    216     return IncludeNode(bits[1])
     249        return ConstantIncludeNode(path[1:-1], extra_context=namemap)
     250    return IncludeNode(parser.compile_filter(bits[1]), extra_context=namemap)
    217251
    218252register.tag('block', do_block)
    219253register.tag('extends', do_extends)
  • docs/ref/templates/builtins.txt

    diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
    index 70f0ffd..35d44fa 100644
    a b including it. This example produces the output ``"Hello, John"``:  
    619619
    620620    * The ``name_snippet.html`` template::
    621621
    622         Hello, {{ person }}
     622        {{ greeting }}, {{ person }}
     623
     624.. versionchanged:: 1.3
     625
     626You can pass additional context to the template using keyword arguments::
     627
     628    {% include "name_snippet.html" with person="Jane" greeting="Hello" "%}
     629
     630This is pretty much syntactic sugar for wrapping :ttag:`include`
     631with a :ttag:`with` tag.
    623632
    624633See also: ``{% ssi %}``.
    625634
  • tests/regressiontests/templates/tests.py

    diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
    index 6683ebb..d85ee5c 100644
    a b class Templates(unittest.TestCase):  
    923923            'include 05': ('template with a space', {}, 'template with a space'),
    924924            'include06': ('{% include "include 05"%}', {}, 'template with a space'),
    925925
     926            # extra inline context
     927            'include07': ('{% include "basic-syntax02" with headline="Inline" %}', {'headline': 'Included'}, 'Inline'),
     928            'include08': ('{% include headline with headline="Dynamic" %}', {'headline': 'basic-syntax02'}, 'Dynamic'),
     929            'include09': ('{{ first }}--{% include "basic-syntax03" with first=second|lower|upper second=first|upper %}--{{ second }}', {'first': 'Ul', 'second': 'lU'}, 'Ul--LU --- UL--lU'),
     930
     931            'include-error01': ('{% include "basic-syntax01" with %}', {}, template.TemplateSyntaxError),
     932            'include-error02': ('{% include "basic-syntax01" with "no key" %}', {}, template.TemplateSyntaxError),
     933            'include-error03': ('{% include "basic-syntax01" with dotted.arg="error" %}', {}, template.TemplateSyntaxError),
     934            'include-error04': ('{% include "basic-syntax01" something_random %}', {}, template.TemplateSyntaxError),
     935            'include-error05': ('{% include "basic-syntax01" foo="duplicate" foo="key" %}', {}, template.TemplateSyntaxError),
     936
    926937            ### NAMED ENDBLOCKS #######################################################
    927938
    928939            # Basic test
Back to Top