Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
Malcolm Tredinnick authored March 23, 2009
55  django/template/defaulttags.py
@@ -39,7 +39,7 @@ def render(self, context):
39 39
 
40 40
 class CycleNode(Node):
41 41
     def __init__(self, cyclevars, variable_name=None):
42  
-        self.cycle_iter = itertools_cycle([Variable(v) for v in cyclevars])
  42
+        self.cycle_iter = itertools_cycle(cyclevars)
43 43
         self.variable_name = variable_name
44 44
 
45 45
     def render(self, context):
@@ -70,14 +70,11 @@ def render(self, context):
70 70
 
71 71
 class FirstOfNode(Node):
72 72
     def __init__(self, vars):
73  
-        self.vars = map(Variable, vars)
  73
+        self.vars = vars
74 74
 
75 75
     def render(self, context):
76 76
         for var in self.vars:
77  
-            try:
78  
-                value = var.resolve(context)
79  
-            except VariableDoesNotExist:
80  
-                continue
  77
+            value = var.resolve(context)
81 78
             if value:
82 79
                 return smart_unicode(value)
83 80
         return u''
@@ -169,7 +166,7 @@ class IfChangedNode(Node):
169 166
     def __init__(self, nodelist_true, nodelist_false, *varlist):
170 167
         self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
171 168
         self._last_seen = None
172  
-        self._varlist = map(Variable, varlist)
  169
+        self._varlist = varlist
173 170
         self._id = str(id(self))
174 171
 
175 172
     def render(self, context):
@@ -180,7 +177,7 @@ def render(self, context):
180 177
             if self._varlist:
181 178
                 # Consider multiple parameters.  This automatically behaves
182 179
                 # like an OR evaluation of the multiple variables.
183  
-                compare_to = [var.resolve(context) for var in self._varlist]
  180
+                compare_to = [var.resolve(context, True) for var in self._varlist]
184 181
             else:
185 182
                 compare_to = self.nodelist_true.render(context)
186 183
         except VariableDoesNotExist:
@@ -200,7 +197,7 @@ def render(self, context):
200 197
 
201 198
 class IfEqualNode(Node):
202 199
     def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
203  
-        self.var1, self.var2 = Variable(var1), Variable(var2)
  200
+        self.var1, self.var2 = var1, var2
204 201
         self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
205 202
         self.negate = negate
206 203
 
@@ -208,14 +205,8 @@ def __repr__(self):
208 205
         return "<IfEqualNode>"
209 206
 
210 207
     def render(self, context):
211  
-        try:
212  
-            val1 = self.var1.resolve(context)
213  
-        except VariableDoesNotExist:
214  
-            val1 = None
215  
-        try:
216  
-            val2 = self.var2.resolve(context)
217  
-        except VariableDoesNotExist:
218  
-            val2 = None
  208
+        val1 = self.var1.resolve(context, True)
  209
+        val2 = self.var2.resolve(context, True)
219 210
         if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
220 211
             return self.nodelist_true.render(context)
221 212
         return self.nodelist_false.render(context)
@@ -371,11 +362,10 @@ def render(self, context):
371 362
         args = [arg.resolve(context) for arg in self.args]
372 363
         kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
373 364
                        for k, v in self.kwargs.items()])
374  
-        
375  
-        
  365
+
376 366
         # Try to look up the URL twice: once given the view name, and again
377  
-        # relative to what we guess is the "main" app. If they both fail, 
378  
-        # re-raise the NoReverseMatch unless we're using the 
  367
+        # relative to what we guess is the "main" app. If they both fail,
  368
+        # re-raise the NoReverseMatch unless we're using the
379 369
         # {% url ... as var %} construct in which cause return nothing.
380 370
         url = ''
381 371
         try:
@@ -388,7 +378,7 @@ def render(self, context):
388 378
             except NoReverseMatch:
389 379
                 if self.asvar is None:
390 380
                     raise
391  
-                    
  381
+
392 382
         if self.asvar:
393 383
             context[self.asvar] = url
394 384
             return ''
@@ -514,12 +504,14 @@ def cycle(parser, token):
514 504
 
515 505
     if len(args) > 4 and args[-2] == 'as':
516 506
         name = args[-1]
517  
-        node = CycleNode(args[1:-2], name)
  507
+        values = [parser.compile_filter(arg) for arg in args[1:-2]]
  508
+        node = CycleNode(values, name)
518 509
         if not hasattr(parser, '_namedCycleNodes'):
519 510
             parser._namedCycleNodes = {}
520 511
         parser._namedCycleNodes[name] = node
521 512
     else:
522  
-        node = CycleNode(args[1:])
  513
+        values = [parser.compile_filter(arg) for arg in args[1:]]
  514
+        node = CycleNode(values)
523 515
     return node
524 516
 cycle = register.tag(cycle)
525 517
 
@@ -594,7 +586,7 @@ def firstof(parser, token):
594 586
     if len(bits) < 1:
595 587
         raise TemplateSyntaxError("'firstof' statement requires at least one"
596 588
                                   " argument")
597  
-    return FirstOfNode(bits)
  589
+    return FirstOfNode([parser.compile_filter(bit) for bit in bits])
598 590
 firstof = register.tag(firstof)
599 591
 
600 592
 #@register.tag(name="for")
@@ -629,10 +621,10 @@ def do_for(parser, token):
629 621
             <li>Sorry, no athletes in this list.</li>
630 622
           {% endfor %}
631 623
         <ul>
632  
-        
  624
+
633 625
     The above is equivalent to -- but shorter, cleaner, and possibly faster
634 626
     than -- the following::
635  
-    
  627
+
636 628
         <ul>
637 629
           {% if althete_list %}
638 630
             {% for athlete in athlete_list %}
@@ -701,7 +693,9 @@ def do_ifequal(parser, token, negate):
701 693
         parser.delete_first_token()
702 694
     else:
703 695
         nodelist_false = NodeList()
704  
-    return IfEqualNode(bits[1], bits[2], nodelist_true, nodelist_false, negate)
  696
+    val1 = parser.compile_filter(bits[1])
  697
+    val2 = parser.compile_filter(bits[2])
  698
+    return IfEqualNode(val1, val2, nodelist_true, nodelist_false, negate)
705 699
 
706 700
 #@register.tag
707 701
 def ifequal(parser, token):
@@ -864,7 +858,8 @@ def ifchanged(parser, token):
864 858
         parser.delete_first_token()
865 859
     else:
866 860
         nodelist_false = NodeList()
867  
-    return IfChangedNode(nodelist_true, nodelist_false, *bits[1:])
  861
+    values = [parser.compile_filter(bit) for bit in bits[1:]]
  862
+    return IfChangedNode(nodelist_true, nodelist_false, *values)
868 863
 ifchanged = register.tag(ifchanged)
869 864
 
870 865
 #@register.tag
@@ -1105,7 +1100,7 @@ def url(parser, token):
1105 1100
     args = []
1106 1101
     kwargs = {}
1107 1102
     asvar = None
1108  
-        
  1103
+
1109 1104
     if len(bits) > 2:
1110 1105
         bits = iter(bits[2:])
1111 1106
         for bit in bits:
9  tests/regressiontests/templates/tests.py
@@ -424,13 +424,13 @@ def get_template_tests(self):
424 424
             'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
425 425
             'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
426 426
             'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
427  
-            # New format:
428 427
             'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),
429 428
             'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),
430 429
             'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),
431 430
             'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
432 431
             'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
433 432
             'cycle15': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),
  433
+            'cycle16': ("{% cycle one|lower two as foo %}{% cycle foo %}", {'one': 'A','two': '2'}, 'a2'),
434 434
 
435 435
             ### EXCEPTIONS ############################################################
436 436
 
@@ -638,6 +638,13 @@ def get_template_tests(self):
638 638
             'ifequal-numeric11': ('{% ifequal x -5.2 %}yes{% endifequal %}', {'x': -5.2}, 'yes'),
639 639
             'ifequal-numeric12': ('{% ifequal x +5 %}yes{% endifequal %}', {'x': 5}, 'yes'),
640 640
 
  641
+            # FILTER EXPRESSIONS AS ARGUMENTS
  642
+            'ifequal-filter01': ('{% ifequal a|upper "A" %}x{% endifequal %}', {'a': 'a'}, 'x'),
  643
+            'ifequal-filter02': ('{% ifequal "A" a|upper %}x{% endifequal %}', {'a': 'a'}, 'x'),
  644
+            'ifequal-filter03': ('{% ifequal a|upper b|upper %}x{% endifequal %}', {'a': 'x', 'b': 'X'}, 'x'),
  645
+            'ifequal-filter04': ('{% ifequal x|slice:"1" "a" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),
  646
+            'ifequal-filter05': ('{% ifequal x|slice:"1"|upper "A" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),
  647
+
641 648
             ### IFNOTEQUAL TAG ########################################################
642 649
             'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
643 650
             'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),

0 notes on commit 7db24dd

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