Skip to content

Commit

Permalink
Fixed #14046 -- Made {% include %} behave the same, regardless of whe…
Browse files Browse the repository at this point in the history
…ther 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
  • Loading branch information
russellm committed Feb 4, 2011
1 parent acfbb27 commit f1ed3b1
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 27 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
4 changes: 1 addition & 3 deletions django/template/loader_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,10 @@ def render(self, context):
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):
"""
Expand Down
7 changes: 7 additions & 0 deletions tests/regressiontests/templates/templatetags/bad_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django import template

register = template.Library()

@register.tag
def badtag(parser, token):
raise RuntimeError("I am a bad tag")
2 changes: 1 addition & 1 deletion tests/regressiontests/templates/templatetags/broken_tag.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from django import Xtemplate
from django import Xtemplate
68 changes: 45 additions & 23 deletions tests/regressiontests/templates/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,46 +389,59 @@ def test_template_loader(template_name, template_dirs=None):
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]:
Expand Down Expand Up @@ -616,7 +629,7 @@ def get_template_tests(self):

# 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'),
Expand Down Expand Up @@ -645,8 +658,8 @@ def get_template_tests(self):
# 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"),
Expand Down Expand Up @@ -699,7 +712,7 @@ def get_template_tests(self):
### 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)),
Expand Down Expand Up @@ -968,7 +981,7 @@ def get_template_tests(self):
'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'),

Expand All @@ -989,6 +1002,15 @@ def get_template_tests(self):
'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
Expand Down Expand Up @@ -1230,8 +1252,8 @@ def get_template_tests(self):
'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 #############################################################

Expand Down Expand Up @@ -1393,8 +1415,8 @@ def get_template_tests(self):

# 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),
Expand Down Expand Up @@ -1433,18 +1455,18 @@ def get_template_tests(self):

# 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),
'url-fail07': ('{% load url from future %}{% url "view" a.id!id %}', {}, template.TemplateSyntaxError),
'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),
Expand Down

0 comments on commit f1ed3b1

Please sign in to comment.