Fixes #1338, Refs #1400, #2237 -- Modified variable resolution to allow template 'if' statements to work if TEMPLATE_STRING_IF_INVALID is set. Modified unit tests to force the use of this variable, so that returning '' isn't confused with an actual failure.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@3268 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
009f224e57
commit
6b383afd39
|
@ -318,7 +318,7 @@ class Parser(object):
|
||||||
self.tags.update(lib.tags)
|
self.tags.update(lib.tags)
|
||||||
self.filters.update(lib.filters)
|
self.filters.update(lib.filters)
|
||||||
|
|
||||||
def compile_filter(self,token):
|
def compile_filter(self, token):
|
||||||
"Convenient wrapper for FilterExpression"
|
"Convenient wrapper for FilterExpression"
|
||||||
return FilterExpression(token, self)
|
return FilterExpression(token, self)
|
||||||
|
|
||||||
|
@ -543,11 +543,14 @@ class FilterExpression(object):
|
||||||
raise TemplateSyntaxError, "Could not parse the remainder: %s" % token[upto:]
|
raise TemplateSyntaxError, "Could not parse the remainder: %s" % token[upto:]
|
||||||
self.var, self.filters = var, filters
|
self.var, self.filters = var, filters
|
||||||
|
|
||||||
def resolve(self, context):
|
def resolve(self, context, ignore_failures=False):
|
||||||
try:
|
try:
|
||||||
obj = resolve_variable(self.var, context)
|
obj = resolve_variable(self.var, context)
|
||||||
except VariableDoesNotExist:
|
except VariableDoesNotExist:
|
||||||
obj = settings.TEMPLATE_STRING_IF_INVALID
|
if ignore_failures:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return settings.TEMPLATE_STRING_IF_INVALID
|
||||||
for func, args in self.filters:
|
for func, args in self.filters:
|
||||||
arg_vals = []
|
arg_vals = []
|
||||||
for lookup, arg in args:
|
for lookup, arg in args:
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Context(object):
|
||||||
for d in self.dicts:
|
for d in self.dicts:
|
||||||
if d.has_key(key):
|
if d.has_key(key):
|
||||||
return d[key]
|
return d[key]
|
||||||
return settings.TEMPLATE_STRING_IF_INVALID
|
raise KeyError(key)
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
"Delete a variable from the current context"
|
"Delete a variable from the current context"
|
||||||
|
@ -49,7 +49,7 @@ class Context(object):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get(self, key, otherwise):
|
def get(self, key, otherwise=None):
|
||||||
for d in self.dicts:
|
for d in self.dicts:
|
||||||
if d.has_key(key):
|
if d.has_key(key):
|
||||||
return d[key]
|
return d[key]
|
||||||
|
|
|
@ -45,7 +45,10 @@ class FirstOfNode(Node):
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
for var in self.vars:
|
for var in self.vars:
|
||||||
value = resolve_variable(var, context)
|
try:
|
||||||
|
value = resolve_variable(var, context)
|
||||||
|
except VariableDoesNotExist:
|
||||||
|
continue
|
||||||
if value:
|
if value:
|
||||||
return str(value)
|
return str(value)
|
||||||
return ''
|
return ''
|
||||||
|
@ -144,8 +147,14 @@ class IfEqualNode(Node):
|
||||||
return "<IfEqualNode>"
|
return "<IfEqualNode>"
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
val1 = resolve_variable(self.var1, context)
|
try:
|
||||||
val2 = resolve_variable(self.var2, context)
|
val1 = resolve_variable(self.var1, context)
|
||||||
|
except VariableDoesNotExist:
|
||||||
|
val1 = None
|
||||||
|
try:
|
||||||
|
val2 = resolve_variable(self.var2, context)
|
||||||
|
except VariableDoesNotExist:
|
||||||
|
val2 = None
|
||||||
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
|
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
|
||||||
return self.nodelist_true.render(context)
|
return self.nodelist_true.render(context)
|
||||||
return self.nodelist_false.render(context)
|
return self.nodelist_false.render(context)
|
||||||
|
@ -177,7 +186,7 @@ class IfNode(Node):
|
||||||
if self.link_type == IfNode.LinkTypes.or_:
|
if self.link_type == IfNode.LinkTypes.or_:
|
||||||
for ifnot, bool_expr in self.bool_exprs:
|
for ifnot, bool_expr in self.bool_exprs:
|
||||||
try:
|
try:
|
||||||
value = bool_expr.resolve(context)
|
value = bool_expr.resolve(context, True)
|
||||||
except VariableDoesNotExist:
|
except VariableDoesNotExist:
|
||||||
value = None
|
value = None
|
||||||
if (value and not ifnot) or (ifnot and not value):
|
if (value and not ifnot) or (ifnot and not value):
|
||||||
|
@ -186,7 +195,7 @@ class IfNode(Node):
|
||||||
else:
|
else:
|
||||||
for ifnot, bool_expr in self.bool_exprs:
|
for ifnot, bool_expr in self.bool_exprs:
|
||||||
try:
|
try:
|
||||||
value = bool_expr.resolve(context)
|
value = bool_expr.resolve(context, True)
|
||||||
except VariableDoesNotExist:
|
except VariableDoesNotExist:
|
||||||
value = None
|
value = None
|
||||||
if not ((value and not ifnot) or (ifnot and not value)):
|
if not ((value and not ifnot) or (ifnot and not value)):
|
||||||
|
|
|
@ -78,7 +78,7 @@ TEMPLATE_TESTS = {
|
||||||
'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
|
'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
|
||||||
|
|
||||||
# Fail silently when a variable is not found in the current context
|
# Fail silently when a variable is not found in the current context
|
||||||
'basic-syntax04': ("as{{ missing }}df", {}, "asdf"),
|
'basic-syntax04': ("as{{ missing }}df", {}, "asINVALIDdf"),
|
||||||
|
|
||||||
# A variable may not contain more than one word
|
# A variable may not contain more than one word
|
||||||
'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
|
'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
|
||||||
|
@ -94,7 +94,7 @@ TEMPLATE_TESTS = {
|
||||||
'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
|
'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
|
||||||
|
|
||||||
# Fail silently when a variable's attribute isn't found
|
# Fail silently when a variable's attribute isn't found
|
||||||
'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, ""),
|
'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, "INVALID"),
|
||||||
|
|
||||||
# Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
|
# Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
|
||||||
'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
|
'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
|
||||||
|
@ -110,10 +110,10 @@ TEMPLATE_TESTS = {
|
||||||
'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
|
'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
|
||||||
|
|
||||||
# Fail silently when a variable's dictionary key isn't found
|
# Fail silently when a variable's dictionary key isn't found
|
||||||
'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, ""),
|
'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, "INVALID"),
|
||||||
|
|
||||||
# Fail silently when accessing a non-simple method
|
# Fail silently when accessing a non-simple method
|
||||||
'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ""),
|
'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, "INVALID"),
|
||||||
|
|
||||||
# Basic filter usage
|
# Basic filter usage
|
||||||
'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
|
'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
|
||||||
|
@ -152,7 +152,7 @@ TEMPLATE_TESTS = {
|
||||||
'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
|
'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
|
||||||
|
|
||||||
# Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
|
# Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
|
||||||
'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "12"),
|
'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "1INVALID2"),
|
||||||
|
|
||||||
# In methods that raise an exception without a "silent_variable_attribute" set to True,
|
# In methods that raise an exception without a "silent_variable_attribute" set to True,
|
||||||
# the exception propogates
|
# the exception propogates
|
||||||
|
@ -495,7 +495,7 @@ TEMPLATE_TESTS = {
|
||||||
'{{ item.foo }}' + \
|
'{{ item.foo }}' + \
|
||||||
'{% endfor %},' + \
|
'{% endfor %},' + \
|
||||||
'{% endfor %}',
|
'{% endfor %}',
|
||||||
{}, ''),
|
{}, 'INVALID:INVALIDINVALIDINVALIDINVALIDINVALIDINVALIDINVALID,'),
|
||||||
|
|
||||||
### TEMPLATETAG TAG #######################################################
|
### TEMPLATETAG TAG #######################################################
|
||||||
'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
|
'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
|
||||||
|
@ -579,6 +579,9 @@ def run_tests(verbosity=0, standalone=False):
|
||||||
|
|
||||||
# Turn TEMPLATE_DEBUG off, because tests assume that.
|
# Turn TEMPLATE_DEBUG off, because tests assume that.
|
||||||
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
|
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
|
||||||
|
# Set TEMPLATE_STRING_IF_INVALID to a known string
|
||||||
|
old_invalid, settings.TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID, 'INVALID'
|
||||||
|
|
||||||
for name, vals in tests:
|
for name, vals in tests:
|
||||||
install()
|
install()
|
||||||
if 'LANGUAGE_CODE' in vals[1]:
|
if 'LANGUAGE_CODE' in vals[1]:
|
||||||
|
@ -609,6 +612,7 @@ def run_tests(verbosity=0, standalone=False):
|
||||||
loader.template_source_loaders = old_template_loaders
|
loader.template_source_loaders = old_template_loaders
|
||||||
deactivate()
|
deactivate()
|
||||||
settings.TEMPLATE_DEBUG = old_td
|
settings.TEMPLATE_DEBUG = old_td
|
||||||
|
settings.TEMPLATE_STRING_IF_INVALID = old_invalid
|
||||||
|
|
||||||
if failed_tests and not standalone:
|
if failed_tests and not standalone:
|
||||||
msg = "Template tests %s failed." % failed_tests
|
msg = "Template tests %s failed." % failed_tests
|
||||||
|
|
Loading…
Reference in New Issue