diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index c08ecc4..ca1fd3f 100644
a
|
b
|
class WidthRatioNode(Node):
|
406 | 406 | return str(int(round(ratio))) |
407 | 407 | |
408 | 408 | class 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 |
412 | 412 | self.nodelist = nodelist |
413 | 413 | |
414 | 414 | def __repr__(self): |
415 | 415 | return "<WithNode>" |
416 | 416 | |
417 | 417 | def render(self, context): |
418 | | val = self.var.resolve(context) |
419 | 418 | context.push() |
420 | | context[self.name] = val |
| 419 | for name, var in zip(self.namelist, self.varlist): |
| 420 | context[name] = var.resolve(context) |
421 | 421 | output = self.nodelist.render(context) |
422 | 422 | context.pop() |
423 | 423 | return output |
… |
… |
widthratio = register.tag(widthratio)
|
1148 | 1148 | def do_with(parser, token): |
1149 | 1149 | """ |
1150 | 1150 | 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. |
1152 | 1153 | |
1153 | 1154 | For example:: |
1154 | 1155 | |
1155 | 1156 | {% with person.some_sql_method as total %} |
1156 | 1157 | {{ total }} object{{ total|pluralize }} |
1157 | 1158 | {% endwith %} |
| 1159 | |
| 1160 | {% with value1 as var1 and value2 as var2 %} |
| 1161 | {{ var1 }} ... {{ var2 }} |
| 1162 | {% endwith %} |
1158 | 1163 | """ |
1159 | 1164 | 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] |
1165 | 1180 | nodelist = parser.parse(('endwith',)) |
1166 | 1181 | parser.delete_first_token() |
1167 | | return WithNode(var, name, nodelist) |
| 1182 | return WithNode(varlist, namelist, nodelist) |
1168 | 1183 | do_with = register.tag('with', do_with) |
diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
index 17e6e8b..d98ac9f 100644
a
|
b
|
For example::
|
799 | 799 | The populated variable (in the example above, ``total``) is only available |
800 | 800 | between the ``{% with %}`` and ``{% endwith %}`` tags. |
801 | 801 | |
| 802 | Multiple 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 | |
802 | 808 | .. _ref-templates-builtins-filters: |
803 | 809 | |
804 | 810 | Built-in filter reference |
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 22d7f7d..57554da 100644
a
|
b
|
class Templates(unittest.TestCase):
|
903 | 903 | ### WITH TAG ######################################################## |
904 | 904 | 'with01': ('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'), |
905 | 905 | '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'), |
906 | 908 | |
907 | 909 | 'with-error01': ('{% with dict.key xx key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError), |
908 | 910 | '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), |
909 | 914 | |
910 | 915 | ### NOW TAG ######################################################## |
911 | 916 | # Simple case |