mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Improved {% include %} implementation
Merged BaseIncludeNode, ConstantIncludeNode and Include node. This avoids raising TemplateDoesNotExist at parsing time, allows recursion when passing a literal template name, and should make TEMPLATE_DEBUG behavior consistant. Thanks loic84 for help with the tests. Fixed #3544, fixed #12064, fixed #16147
This commit is contained in:
committed by
Anssi Kääriäinen
parent
e973ee6a98
commit
e2f06226ea
@@ -121,55 +121,34 @@ class ExtendsNode(Node):
|
||||
# the same.
|
||||
return compiled_parent._render(context)
|
||||
|
||||
class BaseIncludeNode(Node):
|
||||
def __init__(self, *args, **kwargs):
|
||||
class IncludeNode(Node):
|
||||
def __init__(self, template, *args, **kwargs):
|
||||
self.template = template
|
||||
self.extra_context = kwargs.pop('extra_context', {})
|
||||
self.isolated_context = kwargs.pop('isolated_context', False)
|
||||
super(BaseIncludeNode, self).__init__(*args, **kwargs)
|
||||
|
||||
def render_template(self, template, context):
|
||||
values = dict([(name, var.resolve(context)) for name, var
|
||||
in six.iteritems(self.extra_context)])
|
||||
if self.isolated_context:
|
||||
return template.render(context.new(values))
|
||||
with context.push(**values):
|
||||
return template.render(context)
|
||||
|
||||
|
||||
class ConstantIncludeNode(BaseIncludeNode):
|
||||
def __init__(self, template_path, *args, **kwargs):
|
||||
super(ConstantIncludeNode, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
t = get_template(template_path)
|
||||
self.template = t
|
||||
except:
|
||||
if settings.TEMPLATE_DEBUG:
|
||||
raise
|
||||
self.template = None
|
||||
|
||||
def render(self, context):
|
||||
if not self.template:
|
||||
return ''
|
||||
return self.render_template(self.template, context)
|
||||
|
||||
class IncludeNode(BaseIncludeNode):
|
||||
def __init__(self, template_name, *args, **kwargs):
|
||||
super(IncludeNode, self).__init__(*args, **kwargs)
|
||||
self.template_name = template_name
|
||||
|
||||
def render(self, context):
|
||||
try:
|
||||
template = self.template_name.resolve(context)
|
||||
template = self.template.resolve(context)
|
||||
# Does this quack like a Template?
|
||||
if not callable(getattr(template, 'render', None)):
|
||||
# If not, we'll try get_template
|
||||
template = get_template(template)
|
||||
return self.render_template(template, context)
|
||||
values = {
|
||||
name: var.resolve(context)
|
||||
for name, var in six.iteritems(self.extra_context)
|
||||
}
|
||||
if self.isolated_context:
|
||||
return template.render(context.new(values))
|
||||
with context.push(**values):
|
||||
return template.render(context)
|
||||
except:
|
||||
if settings.TEMPLATE_DEBUG:
|
||||
raise
|
||||
return ''
|
||||
|
||||
|
||||
@register.tag('block')
|
||||
def do_block(parser, token):
|
||||
"""
|
||||
@@ -258,9 +237,5 @@ def do_include(parser, token):
|
||||
options[option] = value
|
||||
isolated_context = options.get('only', False)
|
||||
namemap = options.get('with', {})
|
||||
path = bits[1]
|
||||
if path[0] in ('"', "'") and path[-1] == path[0]:
|
||||
return ConstantIncludeNode(path[1:-1], extra_context=namemap,
|
||||
isolated_context=isolated_context)
|
||||
return IncludeNode(parser.compile_filter(bits[1]), extra_context=namemap,
|
||||
isolated_context=isolated_context)
|
||||
|
||||
Reference in New Issue
Block a user