Fixed #14046 -- Made {% include %} behave the same, regardless of whether the template included is named by variable or constant string. Thanks to defcube for the report, and George Karpenkov for the draft patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15413 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2011-02-04 17:10:21 +00:00
parent 1a2f9ff9f9
commit d8c38bd2c9
5 changed files with 55 additions and 27 deletions

View File

@ -258,6 +258,7 @@ answer newbie questions, and generally made Django that much better:
Bahadır Kandemir <bahadir@pardus.org.tr>
Karderio <karderio@gmail.com>
Nagy Károly <charlie@rendszergazda.com>
George Karpenkov <george@metaworld.ru>
Erik Karulf <erik@karulf.com>
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
Ian G. Kelly <ian.g.kelly@gmail.com>

View File

@ -168,12 +168,10 @@ class IncludeNode(BaseIncludeNode):
template_name = self.template_name.resolve(context)
template = get_template(template_name)
return self.render_template(template, context)
except TemplateSyntaxError:
except:
if settings.TEMPLATE_DEBUG:
raise
return ''
except:
return '' # Fail silently for invalid included templates.
def do_block(parser, token):
"""

View File

@ -0,0 +1,7 @@
from django import template
register = template.Library()
@register.tag
def badtag(parser, token):
raise RuntimeError("I am a bad tag")

View File

@ -1 +1 @@
from django import Xtemplate
from django import Xtemplate

View File

@ -389,46 +389,59 @@ class Templates(unittest.TestCase):
if isinstance(vals[2], tuple):
normal_string_result = vals[2][0]
invalid_string_result = vals[2][1]
if isinstance(invalid_string_result, basestring) and '%s' in invalid_string_result:
if isinstance(invalid_string_result, tuple):
expected_invalid_str = 'INVALID %s'
invalid_string_result = invalid_string_result % vals[2][2]
invalid_string_result = invalid_string_result[0] % invalid_string_result[1]
template_base.invalid_var_format_string = True
try:
template_debug_result = vals[2][2]
except IndexError:
template_debug_result = normal_string_result
else:
normal_string_result = vals[2]
invalid_string_result = vals[2]
template_debug_result = vals[2]
if 'LANGUAGE_CODE' in vals[1]:
activate(vals[1]['LANGUAGE_CODE'])
else:
activate('en-us')
for invalid_str, result in [('', normal_string_result),
(expected_invalid_str, invalid_string_result)]:
for invalid_str, template_debug, result in [
('', False, normal_string_result),
(expected_invalid_str, False, invalid_string_result),
('', True, template_debug_result)
]:
settings.TEMPLATE_STRING_IF_INVALID = invalid_str
settings.TEMPLATE_DEBUG = template_debug
for is_cached in (False, True):
try:
start = datetime.now()
test_template = loader.get_template(name)
end = datetime.now()
if end-start > timedelta(seconds=0.2):
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to parse test" % (is_cached, invalid_str, name))
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Took too long to parse test" % (is_cached, invalid_str, template_debug, name))
start = datetime.now()
output = self.render(test_template, vals)
end = datetime.now()
if end-start > timedelta(seconds=0.2):
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to render test" % (is_cached, invalid_str, name))
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Took too long to render test" % (is_cached, invalid_str, template_debug, name))
except ContextStackException:
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, name))
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, template_debug, name))
continue
except Exception:
exc_type, exc_value, exc_tb = sys.exc_info()
if exc_type != result:
print "CHECK", name, exc_type, result
tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb))
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s\n%s" % (is_cached, invalid_str, name, exc_type, exc_value, tb))
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Got %s, exception: %s\n%s" % (is_cached, invalid_str, template_debug, name, exc_type, exc_value, tb))
continue
if output != result:
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (is_cached, invalid_str, name, result, output))
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Expected %r, got %r" % (is_cached, invalid_str, template_debug, name, result, output))
cache_loader.reset()
if 'LANGUAGE_CODE' in vals[1]:
@ -616,7 +629,7 @@ class Templates(unittest.TestCase):
# In methods that raise an exception without a
# "silent_variable_attribute" set to True, the exception propagates
'filter-syntax14': (r'1{{ var.method4 }}2', {"var": SomeClass()}, SomeOtherException),
'filter-syntax14': (r'1{{ var.method4 }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException, template.TemplateSyntaxError)),
# Escaped backslash in argument
'filter-syntax15': (r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'),
@ -645,8 +658,8 @@ class Templates(unittest.TestCase):
# In attribute and dict lookups that raise an unexpected exception
# without a "silent_variable_attribute" set to True, the exception
# propagates
'filter-syntax23': (r'1{{ var.noisy_fail_key }}2', {"var": SomeClass()}, SomeOtherException),
'filter-syntax24': (r'1{{ var.noisy_fail_attribute }}2', {"var": SomeClass()}, SomeOtherException),
'filter-syntax23': (r'1{{ var.noisy_fail_key }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException, template.TemplateSyntaxError)),
'filter-syntax24': (r'1{{ var.noisy_fail_attribute }}2', {"var": SomeClass()}, (SomeOtherException, SomeOtherException, template.TemplateSyntaxError)),
### COMMENT SYNTAX ########################################################
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
@ -699,7 +712,7 @@ class Templates(unittest.TestCase):
### EXCEPTIONS ############################################################
# Raise exception for invalid template name
'exception01': ("{% extends 'nonexistent' %}", {}, template.TemplateDoesNotExist),
'exception01': ("{% extends 'nonexistent' %}", {}, (template.TemplateDoesNotExist, template.TemplateDoesNotExist, template.TemplateSyntaxError)),
# Raise exception for invalid template name (in variable)
'exception02': ("{% extends nonexistent %}", {}, (template.TemplateSyntaxError, template.TemplateDoesNotExist)),
@ -968,7 +981,7 @@ class Templates(unittest.TestCase):
'include01': ('{% include "basic-syntax01" %}', {}, "something cool"),
'include02': ('{% include "basic-syntax02" %}', {'headline': 'Included'}, "Included"),
'include03': ('{% include template_name %}', {'template_name': 'basic-syntax02', 'headline': 'Included'}, "Included"),
'include04': ('a{% include "nonexistent" %}b', {}, "ab"),
'include04': ('a{% include "nonexistent" %}b', {}, ("ab", "ab", template.TemplateDoesNotExist)),
'include 05': ('template with a space', {}, 'template with a space'),
'include06': ('{% include "include 05"%}', {}, 'template with a space'),
@ -989,6 +1002,15 @@ class Templates(unittest.TestCase):
'include-error05': ('{% include "basic-syntax01" foo="duplicate" foo="key" %}', {}, template.TemplateSyntaxError),
'include-error06': ('{% include "basic-syntax01" only only %}', {}, template.TemplateSyntaxError),
### INCLUSION ERROR REPORTING #############################################
'include-fail1': ('{% load bad_tag %}{% badtag %}', {}, RuntimeError),
'include-fail2': ('{% load broken_tag %}', {}, template.TemplateSyntaxError),
'include-error07': ('{% include "include-fail1" %}', {}, ('', '', RuntimeError)),
'include-error08': ('{% include "include-fail2" %}', {}, ('', '', template.TemplateSyntaxError)),
'include-error09': ('{% include failed_include %}', {'failed_include': 'include-fail1'}, ('', '', template.TemplateSyntaxError)),
'include-error10': ('{% include failed_include %}', {'failed_include': 'include-fail2'}, ('', '', template.TemplateSyntaxError)),
### NAMED ENDBLOCKS #######################################################
# Basic test
@ -1230,8 +1252,8 @@ class Templates(unittest.TestCase):
'invalidstr03': ('{% for v in var %}({{ v }}){% endfor %}', {}, ''),
'invalidstr04': ('{% if var %}Yes{% else %}No{% endif %}', {}, 'No'),
'invalidstr04': ('{% if var|default:"Foo" %}Yes{% else %}No{% endif %}', {}, 'Yes'),
'invalidstr05': ('{{ var }}', {}, ('', 'INVALID %s', 'var')),
'invalidstr06': ('{{ var.prop }}', {'var': {}}, ('', 'INVALID %s', 'var.prop')),
'invalidstr05': ('{{ var }}', {}, ('', ('INVALID %s', 'var'))),
'invalidstr06': ('{{ var.prop }}', {'var': {}}, ('', ('INVALID %s', 'var.prop'))),
### MULTILINE #############################################################
@ -1393,8 +1415,8 @@ class Templates(unittest.TestCase):
# Failures
'old-url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
'old-url-fail02': ('{% url no_such_view %}', {}, urlresolvers.NoReverseMatch),
'old-url-fail03': ('{% url regressiontests.templates.views.client %}', {}, urlresolvers.NoReverseMatch),
'old-url-fail02': ('{% url no_such_view %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch, template.TemplateSyntaxError)),
'old-url-fail03': ('{% url regressiontests.templates.views.client %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch, template.TemplateSyntaxError)),
'old-url-fail04': ('{% url view id, %}', {}, template.TemplateSyntaxError),
'old-url-fail05': ('{% url view id= %}', {}, template.TemplateSyntaxError),
'old-url-fail06': ('{% url view a.id=id %}', {}, template.TemplateSyntaxError),
@ -1433,8 +1455,8 @@ class Templates(unittest.TestCase):
# Failures
'url-fail01': ('{% load url from future %}{% url %}', {}, template.TemplateSyntaxError),
'url-fail02': ('{% load url from future %}{% url "no_such_view" %}', {}, urlresolvers.NoReverseMatch),
'url-fail03': ('{% load url from future %}{% url "regressiontests.templates.views.client" %}', {}, urlresolvers.NoReverseMatch),
'url-fail02': ('{% load url from future %}{% url "no_such_view" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch, template.TemplateSyntaxError)),
'url-fail03': ('{% load url from future %}{% url "regressiontests.templates.views.client" %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch, template.TemplateSyntaxError)),
'url-fail04': ('{% load url from future %}{% url "view" id, %}', {}, template.TemplateSyntaxError),
'url-fail05': ('{% load url from future %}{% url "view" id= %}', {}, template.TemplateSyntaxError),
'url-fail06': ('{% load url from future %}{% url "view" a.id=id %}', {}, template.TemplateSyntaxError),
@ -1442,9 +1464,9 @@ class Templates(unittest.TestCase):
'url-fail08': ('{% load url from future %}{% url "view" id="unterminatedstring %}', {}, template.TemplateSyntaxError),
'url-fail09': ('{% load url from future %}{% url "view" id=", %}', {}, template.TemplateSyntaxError),
'url-fail11': ('{% load url from future %}{% url named_url %}', {}, urlresolvers.NoReverseMatch),
'url-fail12': ('{% load url from future %}{% url named_url %}', {'named_url': 'no_such_view'}, urlresolvers.NoReverseMatch),
'url-fail13': ('{% load url from future %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, urlresolvers.NoReverseMatch),
'url-fail11': ('{% load url from future %}{% url named_url %}', {}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch, template.TemplateSyntaxError)),
'url-fail12': ('{% load url from future %}{% url named_url %}', {'named_url': 'no_such_view'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch, template.TemplateSyntaxError)),
'url-fail13': ('{% load url from future %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, (urlresolvers.NoReverseMatch, urlresolvers.NoReverseMatch, template.TemplateSyntaxError)),
'url-fail14': ('{% load url from future %}{% url named_url id, %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail15': ('{% load url from future %}{% url named_url id= %}', {'named_url': 'view'}, template.TemplateSyntaxError),
'url-fail16': ('{% load url from future %}{% url named_url a.id=id %}', {'named_url': 'view'}, template.TemplateSyntaxError),