Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixes #2637 -- Clarified handling of TEMPLATE_STRING_IF_INVALID, espe…

…cially with regards to filtering of invalid values. Modified unit tests to test both empty and non-empty values for TEMPLATE_STRING_IF_INVALID. Thanks to SmileyChris for identifying and helping to resolve this bug.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3714 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit cfe77946d70361c338a431bf661bb19e3870eab2 1 parent 3a919db
Russell Keith-Magee authored September 04, 2006
3  AUTHORS
@@ -104,7 +104,6 @@ answer newbie questions, and generally made Django that much better:
104 104
     mattycakes@gmail.com
105 105
     Jason McBrayer <http://www.carcosa.net/jason/>
106 106
     michael.mcewan@gmail.com
107  
-    mir@noris.de
108 107
     mmarshall
109 108
     Eric Moritz <http://eric.themoritzfamily.com/>
110 109
     Robin Munn <http://www.geekforgod.com/>
@@ -121,12 +120,14 @@ answer newbie questions, and generally made Django that much better:
121 120
     plisk
122 121
     Daniel Poelzleithner <http://poelzi.org/>
123 122
     J. Rademaker
  123
+    Michael Radziej <mir@noris.de>
124 124
     Brian Ray <http://brianray.chipy.org/>
125 125
     rhettg@gmail.com
126 126
     Oliver Rutherfurd <http://rutherfurd.net/>
127 127
     Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
128 128
     David Schein
129 129
     Pete Shinners <pete@shinners.org>
  130
+    SmileyChris <smileychris@gmail.com>
130 131
     sopel
131 132
     Thomas Steinacher <tom@eggdrop.ch>
132 133
     Radek Švarz <http://www.svarz.cz/translate/>
7  django/template/__init__.py
@@ -549,9 +549,12 @@ def resolve(self, context, ignore_failures=False):
549 549
             obj = resolve_variable(self.var, context)
550 550
         except VariableDoesNotExist:
551 551
             if ignore_failures:
552  
-                return None
  552
+                obj = None
553 553
             else:
554  
-                return settings.TEMPLATE_STRING_IF_INVALID
  554
+                if settings.TEMPLATE_STRING_IF_INVALID:
  555
+                    return settings.TEMPLATE_STRING_IF_INVALID
  556
+                else:
  557
+                    obj = settings.TEMPLATE_STRING_IF_INVALID
555 558
         for func, args in self.filters:
556 559
             arg_vals = []
557 560
             for lookup, arg in args:
8  django/template/defaulttags.py
@@ -86,7 +86,7 @@ def render(self, context):
86 86
             parentloop = {}
87 87
         context.push()
88 88
         try:
89  
-            values = self.sequence.resolve(context)
  89
+            values = self.sequence.resolve(context, True)
90 90
         except VariableDoesNotExist:
91 91
             values = []
92 92
         if values is None:
@@ -212,13 +212,13 @@ def __init__(self, target, expression, var_name):
212 212
         self.var_name = var_name
213 213
 
214 214
     def render(self, context):
215  
-        obj_list = self.target.resolve(context)
216  
-        if obj_list == '': # target_var wasn't found in context; fail silently
  215
+        obj_list = self.target.resolve(context, True)
  216
+        if obj_list == None: # target_var wasn't found in context; fail silently
217 217
             context[self.var_name] = []
218 218
             return ''
219 219
         output = [] # list of dictionaries in the format {'grouper': 'key', 'list': [list of contents]}
220 220
         for obj in obj_list:
221  
-            grouper = self.expression.resolve(Context({'var': obj}))
  221
+            grouper = self.expression.resolve(Context({'var': obj}), True)
222 222
             # TODO: Is this a sensible way to determine equality?
223 223
             if output and repr(output[-1]['grouper']) == repr(grouper):
224 224
                 output[-1]['list'].append(obj)
16  docs/templates_python.txt
@@ -198,9 +198,19 @@ some things to keep in mind:
198 198
 How invalid variables are handled
199 199
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
200 200
 
201  
-If a variable doesn't exist, the template system inserts the value of the
202  
-``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty
203  
-string) by default.
  201
+Generally, if a variable doesn't exist, the template system inserts the
  202
+value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''``
  203
+(the empty string) by default.
  204
+
  205
+Filters that are applied to an invalid variable will only be applied if
  206
+``TEMPLATE_STRING_IF_INVALID`` is set to ``''`` (the empty string). If
  207
+``TEMPLATE_STRING_IF_INVALID`` is set to any other value, variable
  208
+filters will be ignored.
  209
+
  210
+This behaviour is slightly different for the ``if``, ``for`` and ``regroup``
  211
+template tags. If an invalid variable is provided to one of these template
  212
+tags, the variable will be interpreted as ``None``. Filters are always
  213
+applied to invalid variables within these template tags.
204 214
 
205 215
 Playing with Context objects
206 216
 ----------------------------
54  tests/regressiontests/templates/tests.py
@@ -84,7 +84,7 @@ def test_templates(self):
84 84
             'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
85 85
 
86 86
             # Fail silently when a variable is not found in the current context
87  
-            'basic-syntax04': ("as{{ missing }}df", {}, "asINVALIDdf"),
  87
+            'basic-syntax04': ("as{{ missing }}df", {}, ("asdf","asINVALIDdf")),
88 88
 
89 89
             # A variable may not contain more than one word
90 90
             'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
@@ -100,7 +100,7 @@ def test_templates(self):
100 100
             'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
101 101
 
102 102
             # Fail silently when a variable's attribute isn't found
103  
-            'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, "INVALID"),
  103
+            'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, ("","INVALID")),
104 104
 
105 105
             # Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
106 106
             'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
@@ -116,10 +116,10 @@ def test_templates(self):
116 116
             'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
117 117
 
118 118
             # Fail silently when a variable's dictionary key isn't found
119  
-            'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, "INVALID"),
  119
+            'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, ("","INVALID")),
120 120
 
121 121
             # Fail silently when accessing a non-simple method
122  
-            'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, "INVALID"),
  122
+            'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ("","INVALID")),
123 123
 
124 124
             # Basic filter usage
125 125
             'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
@@ -158,7 +158,7 @@ def test_templates(self):
158 158
             'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
159 159
 
160 160
             # Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
161  
-            'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "1INVALID2"),
  161
+            'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, ("12", "1INVALID2")),
162 162
 
163 163
             # In methods that raise an exception without a "silent_variable_attribute" set to True,
164 164
             # the exception propogates
@@ -464,6 +464,14 @@ def test_templates(self):
464 464
             # translation of a constant string
465 465
             'i18n13': ('{{ _("Page not found") }}', {'LANGUAGE_CODE': 'de'}, 'Seite nicht gefunden'),
466 466
 
  467
+            ### HANDLING OF TEMPLATE_TAG_IF_INVALID ###################################
  468
+            
  469
+            'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')),
  470
+            'invalidstr02': ('{{ var|default_if_none:"Foo" }}', {}, ('','INVALID')),
  471
+            'invalidstr03': ('{% for v in var %}({{ v }}){% endfor %}', {}, ''),
  472
+            'invalidstr04': ('{% if var %}Yes{% else %}No{% endif %}', {}, 'No'),
  473
+            'invalidstr04': ('{% if var|default:"Foo" %}Yes{% else %}No{% endif %}', {}, 'Yes'),
  474
+
467 475
             ### MULTILINE #############################################################
468 476
 
469 477
             'multiline01': ("""
@@ -507,7 +515,7 @@ def test_templates(self):
507 515
                           '{{ item.foo }}' + \
508 516
                           '{% endfor %},' + \
509 517
                           '{% endfor %}',
510  
-                          {}, 'INVALID:INVALIDINVALIDINVALIDINVALIDINVALIDINVALIDINVALID,'),
  518
+                          {}, ''),
511 519
 
512 520
             ### TEMPLATETAG TAG #######################################################
513 521
             'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
@@ -592,30 +600,44 @@ def test_template_loader(template_name, template_dirs=None):
592 600
         old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
593 601
         
594 602
         # Set TEMPLATE_STRING_IF_INVALID to a known string 
595  
-        old_invalid, settings.TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID, 'INVALID'
  603
+        old_invalid = settings.TEMPLATE_STRING_IF_INVALID
596 604
     
597 605
         for name, vals in tests:
598 606
             install()
  607
+            
  608
+            if isinstance(vals[2], tuple):
  609
+                normal_string_result = vals[2][0]
  610
+                invalid_string_result = vals[2][1]
  611
+            else:
  612
+                normal_string_result = vals[2]
  613
+                invalid_string_result = vals[2]
  614
+                
599 615
             if 'LANGUAGE_CODE' in vals[1]:
600 616
                 activate(vals[1]['LANGUAGE_CODE'])
601 617
             else:
602 618
                 activate('en-us')
603  
-            try:
604  
-                output = loader.get_template(name).render(template.Context(vals[1]))
605  
-            except Exception, e:
606  
-                if e.__class__ != vals[2]:
607  
-                    failures.append("Template test: %s -- FAILED. Got %s, exception: %s" % (name, e.__class__, e))
608  
-                continue
  619
+
  620
+            for invalid_str, result in [('', normal_string_result),
  621
+                                        ('INVALID', invalid_string_result)]:
  622
+                settings.TEMPLATE_STRING_IF_INVALID = invalid_str
  623
+                try:
  624
+                    output = loader.get_template(name).render(template.Context(vals[1]))
  625
+                except Exception, e:
  626
+                    if e.__class__ != result:
  627
+                        failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s" % (invalid_str, name, e.__class__, e))
  628
+                    continue
  629
+                if output != result:
  630
+                    failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (invalid_str, name, result, output))
  631
+                    
609 632
             if 'LANGUAGE_CODE' in vals[1]:
610 633
                 deactivate()
611  
-            if output != vals[2]:
612  
-                    failures.append("Template test: %s -- FAILED. Expected %r, got %r" % (name, vals[2], output))
  634
+            
613 635
         loader.template_source_loaders = old_template_loaders
614 636
         deactivate()
615 637
         settings.TEMPLATE_DEBUG = old_td
616 638
         settings.TEMPLATE_STRING_IF_INVALID = old_invalid
617 639
 
618  
-        self.assertEqual(failures, [])
  640
+        self.assertEqual(failures, [], '\n'.join(failures))
619 641
 
620 642
 if __name__ == "__main__":
621 643
     unittest.main()

0 notes on commit cfe7794

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