Ticket #7817: 7817-with-tag-multiple-bindings.2.diff

File 7817-with-tag-multiple-bindings.2.diff, 4.9 KB (added by akaihola, 6 years ago)

[patch] Allows multiple bindings in the {% with %} tag. Python <=2.4 compatible with tests and documentation.

  • django/template/defaulttags.py

    diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
    index c08ecc4..ca1fd3f 100644
    a b class WidthRatioNode(Node): 
    406406        return str(int(round(ratio)))
    407407
    408408class WithNode(Node):
    409     def __init__(self, var, name, nodelist):
    410         self.var = var
    411         self.name = name
     409    def __init__(self, varlist, namelist, nodelist):
     410        self.varlist = varlist
     411        self.namelist = namelist
    412412        self.nodelist = nodelist
    413413
    414414    def __repr__(self):
    415415        return "<WithNode>"
    416416
    417417    def render(self, context):
    418         val = self.var.resolve(context)
    419418        context.push()
    420         context[self.name] = val
     419        for name, var in zip(self.namelist, self.varlist):
     420            context[name] = var.resolve(context)
    421421        output = self.nodelist.render(context)
    422422        context.pop()
    423423        return output
    widthratio = register.tag(widthratio) 
    11481148def do_with(parser, token):
    11491149    """
    11501150    Adds a value to the context (inside of this block) for caching and easy
    1151     access.
     1151    access. You bind a value to a new name using ``as``. You can chain multiple
     1152    bindings with ``and`` which are evaluated sequentially.
    11521153
    11531154    For example::
    11541155
    11551156        {% with person.some_sql_method as total %}
    11561157            {{ total }} object{{ total|pluralize }}
    11571158        {% endwith %}
     1159
     1160        {% with value1 as var1 and value2 as var2 %}
     1161            {{ var1 }} ... {{ var2 }}
     1162        {% endwith %}
    11581163    """
    11591164    bits = list(token.split_contents())
    1160     if len(bits) != 4 or bits[2] != "as":
    1161         raise TemplateSyntaxError("%r expected format is 'value as name'" %
    1162                                   bits[0])
    1163     var = parser.compile_filter(bits[1])
    1164     name = bits[3]
     1165    try:
     1166        if len(bits) % 4:
     1167            raise TemplateSyntaxError()
     1168        for b in bits[2::4]:
     1169            if b != 'as':
     1170                raise TemplateSyntaxError()
     1171        for b in bits[4::4]:
     1172            if b != 'and':
     1173                raise TemplateSyntaxError()
     1174    except TemplateSyntaxError:
     1175        raise TemplateSyntaxError("'%s' statements should use the format "
     1176                                  "'with value as name [and value as name]...'"
     1177                                  ": %s" % (bits[0], token.contents))
     1178    varlist = [parser.compile_filter(b) for b in bits[1::4]]
     1179    namelist = bits[3::4]
    11651180    nodelist = parser.parse(('endwith',))
    11661181    parser.delete_first_token()
    1167     return WithNode(var, name, nodelist)
     1182    return WithNode(varlist, namelist, nodelist)
    11681183do_with = register.tag('with', do_with)
  • docs/ref/templates/builtins.txt

    diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
    index 17e6e8b..d98ac9f 100644
    a b For example:: 
    799799The populated variable (in the example above, ``total``) is only available
    800800between the ``{% with %}`` and ``{% endwith %}`` tags.
    801801
     802Multiple variables can be cached by using the word ``"and"`` as a delimiter::
     803
     804    {% with items.0 as first and items|slice:"1:" as rest %}
     805        {{ first }} comes first and {{ rest|join:", " }} follow.
     806    {% endwith %}
     807
    802808.. _ref-templates-builtins-filters:
    803809
    804810Built-in filter reference
  • tests/regressiontests/templates/tests.py

    diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
    index 22d7f7d..57554da 100644
    a b class Templates(unittest.TestCase): 
    903903            ### WITH TAG ########################################################
    904904            'with01': ('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'),
    905905            'with02': ('{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}', {'dict': {'key':50}}, ('50-50-50', 'INVALID50-50-50INVALID')),
     906            'with03': ('{% with dict.k1 as k1 and dict.k2 as k2 %}{{k1}}+{{k2}}{% endwith %}', {'dict': {'k1':3, 'k2':4}}, '3+4'),
     907            'with04': ('{% with l.0 as first and l|slice:"1:" as rest %}{{first}}+{{rest|join:","}}{% endwith %}', {'l':['1','2','3','4']}, '1+2,3,4'),
    906908
    907909            'with-error01': ('{% with dict.key xx key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError),
    908910            'with-error02': ('{% with dict.key as %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError),
     911            'with-error03': ('{% with dict.k1 as k1 and dict.k2 %}{{ key }}{% endwith %}', {'dict': {'k1':3, 'k2':4}}, template.TemplateSyntaxError),
     912            'with-error04': ('{% with dict.k1 equals k1 %}{{ key }}{% endwith %}', {'dict': {'k1':3, 'k2':4}}, template.TemplateSyntaxError),
     913            'with-error05': ('{% with dict.k1 as k1 ; dict.k2 as k2 %}{{ key }}{% endwith %}', {'dict': {'k1':3, 'k2':4}}, template.TemplateSyntaxError),
    909914
    910915            ### NOW TAG ########################################################
    911916            # Simple case
Back to Top