Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #5756, #6296 -- Most template tags can now handle filters in ar…

…guments.

Most of the hard work for this was done by akaihola.

There are still possibly some problems with the i18n template tags,
since they are written quite differently and a few other bug fixes have
to made before they can be fixed.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10119 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 7db24dd2b080f727cd9753161e88faa308514aad 1 parent a6f429e
@malcolmt malcolmt authored
View
55 django/template/defaulttags.py
@@ -39,7 +39,7 @@ def render(self, context):
class CycleNode(Node):
def __init__(self, cyclevars, variable_name=None):
- self.cycle_iter = itertools_cycle([Variable(v) for v in cyclevars])
+ self.cycle_iter = itertools_cycle(cyclevars)
self.variable_name = variable_name
def render(self, context):
@@ -70,14 +70,11 @@ def render(self, context):
class FirstOfNode(Node):
def __init__(self, vars):
- self.vars = map(Variable, vars)
+ self.vars = vars
def render(self, context):
for var in self.vars:
- try:
- value = var.resolve(context)
- except VariableDoesNotExist:
- continue
+ value = var.resolve(context)
if value:
return smart_unicode(value)
return u''
@@ -169,7 +166,7 @@ class IfChangedNode(Node):
def __init__(self, nodelist_true, nodelist_false, *varlist):
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self._last_seen = None
- self._varlist = map(Variable, varlist)
+ self._varlist = varlist
self._id = str(id(self))
def render(self, context):
@@ -180,7 +177,7 @@ def render(self, context):
if self._varlist:
# Consider multiple parameters. This automatically behaves
# like an OR evaluation of the multiple variables.
- compare_to = [var.resolve(context) for var in self._varlist]
+ compare_to = [var.resolve(context, True) for var in self._varlist]
else:
compare_to = self.nodelist_true.render(context)
except VariableDoesNotExist:
@@ -200,7 +197,7 @@ def render(self, context):
class IfEqualNode(Node):
def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
- self.var1, self.var2 = Variable(var1), Variable(var2)
+ self.var1, self.var2 = var1, var2
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self.negate = negate
@@ -208,14 +205,8 @@ def __repr__(self):
return "<IfEqualNode>"
def render(self, context):
- try:
- val1 = self.var1.resolve(context)
- except VariableDoesNotExist:
- val1 = None
- try:
- val2 = self.var2.resolve(context)
- except VariableDoesNotExist:
- val2 = None
+ val1 = self.var1.resolve(context, True)
+ val2 = self.var2.resolve(context, True)
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
return self.nodelist_true.render(context)
return self.nodelist_false.render(context)
@@ -371,11 +362,10 @@ def render(self, context):
args = [arg.resolve(context) for arg in self.args]
kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
for k, v in self.kwargs.items()])
-
-
+
# Try to look up the URL twice: once given the view name, and again
- # relative to what we guess is the "main" app. If they both fail,
- # re-raise the NoReverseMatch unless we're using the
+ # relative to what we guess is the "main" app. If they both fail,
+ # re-raise the NoReverseMatch unless we're using the
# {% url ... as var %} construct in which cause return nothing.
url = ''
try:
@@ -388,7 +378,7 @@ def render(self, context):
except NoReverseMatch:
if self.asvar is None:
raise
-
+
if self.asvar:
context[self.asvar] = url
return ''
@@ -514,12 +504,14 @@ def cycle(parser, token):
if len(args) > 4 and args[-2] == 'as':
name = args[-1]
- node = CycleNode(args[1:-2], name)
+ values = [parser.compile_filter(arg) for arg in args[1:-2]]
+ node = CycleNode(values, name)
if not hasattr(parser, '_namedCycleNodes'):
parser._namedCycleNodes = {}
parser._namedCycleNodes[name] = node
else:
- node = CycleNode(args[1:])
+ values = [parser.compile_filter(arg) for arg in args[1:]]
+ node = CycleNode(values)
return node
cycle = register.tag(cycle)
@@ -594,7 +586,7 @@ def firstof(parser, token):
if len(bits) < 1:
raise TemplateSyntaxError("'firstof' statement requires at least one"
" argument")
- return FirstOfNode(bits)
+ return FirstOfNode([parser.compile_filter(bit) for bit in bits])
firstof = register.tag(firstof)
#@register.tag(name="for")
@@ -629,10 +621,10 @@ def do_for(parser, token):
<li>Sorry, no athletes in this list.</li>
{% endfor %}
<ul>
-
+
The above is equivalent to -- but shorter, cleaner, and possibly faster
than -- the following::
-
+
<ul>
{% if althete_list %}
{% for athlete in athlete_list %}
@@ -701,7 +693,9 @@ def do_ifequal(parser, token, negate):
parser.delete_first_token()
else:
nodelist_false = NodeList()
- return IfEqualNode(bits[1], bits[2], nodelist_true, nodelist_false, negate)
+ val1 = parser.compile_filter(bits[1])
+ val2 = parser.compile_filter(bits[2])
+ return IfEqualNode(val1, val2, nodelist_true, nodelist_false, negate)
#@register.tag
def ifequal(parser, token):
@@ -864,7 +858,8 @@ def ifchanged(parser, token):
parser.delete_first_token()
else:
nodelist_false = NodeList()
- return IfChangedNode(nodelist_true, nodelist_false, *bits[1:])
+ values = [parser.compile_filter(bit) for bit in bits[1:]]
+ return IfChangedNode(nodelist_true, nodelist_false, *values)
ifchanged = register.tag(ifchanged)
#@register.tag
@@ -1105,7 +1100,7 @@ def url(parser, token):
args = []
kwargs = {}
asvar = None
-
+
if len(bits) > 2:
bits = iter(bits[2:])
for bit in bits:
View
9 tests/regressiontests/templates/tests.py
@@ -424,13 +424,13 @@ def get_template_tests(self):
'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
- # New format:
'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),
'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),
'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),
'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
'cycle15': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),
+ 'cycle16': ("{% cycle one|lower two as foo %}{% cycle foo %}", {'one': 'A','two': '2'}, 'a2'),
### EXCEPTIONS ############################################################
@@ -638,6 +638,13 @@ def get_template_tests(self):
'ifequal-numeric11': ('{% ifequal x -5.2 %}yes{% endifequal %}', {'x': -5.2}, 'yes'),
'ifequal-numeric12': ('{% ifequal x +5 %}yes{% endifequal %}', {'x': 5}, 'yes'),
+ # FILTER EXPRESSIONS AS ARGUMENTS
+ 'ifequal-filter01': ('{% ifequal a|upper "A" %}x{% endifequal %}', {'a': 'a'}, 'x'),
+ 'ifequal-filter02': ('{% ifequal "A" a|upper %}x{% endifequal %}', {'a': 'a'}, 'x'),
+ 'ifequal-filter03': ('{% ifequal a|upper b|upper %}x{% endifequal %}', {'a': 'x', 'b': 'X'}, 'x'),
+ 'ifequal-filter04': ('{% ifequal x|slice:"1" "a" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),
+ 'ifequal-filter05': ('{% ifequal x|slice:"1"|upper "A" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),
+
### IFNOTEQUAL TAG ########################################################
'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
Please sign in to comment.
Something went wrong with that request. Please try again.