diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py
index 7b4de9a..2655b88 100644
|
a
|
b
|
from collections import defaultdict
|
| 6 | 6 | from django.utils.deprecation import RemovedInDjango21Warning |
| 7 | 7 | from django.utils.safestring import mark_safe |
| 8 | 8 | |
| | 9 | from . import engines |
| 9 | 10 | from .base import ( |
| 10 | 11 | Node, Template, TemplateSyntaxError, TextNode, Variable, token_kwargs, |
| 11 | 12 | ) |
| … |
… |
BLOCK_CONTEXT_KEY = 'block_context'
|
| 18 | 19 | logger = logging.getLogger('django.template') |
| 19 | 20 | |
| 20 | 21 | |
| | 22 | class DifferentTemplateEngineError(Exception): |
| | 23 | pass |
| | 24 | |
| | 25 | |
| 21 | 26 | class BlockContext: |
| 22 | 27 | def __init__(self): |
| 23 | 28 | # Dictionary of FIFO queues. |
| … |
… |
class IncludeNode(Node):
|
| 183 | 188 | # Use the base.Template of a backends.django.Template. |
| 184 | 189 | elif hasattr(template, 'template'): |
| 185 | 190 | template = template.template |
| | 191 | |
| | 192 | if context.template.engine != template.engine: |
| | 193 | raise DifferentTemplateEngineError( |
| | 194 | 'Included template %r is from engine %r but parent template ' |
| | 195 | '%r is from engine %r. Including a template from a ' |
| | 196 | 'different engine is prohibited.' % ( |
| | 197 | template.name, |
| | 198 | engines.get_name_from_engine(template.engine), |
| | 199 | context.template.name, |
| | 200 | engines.get_name_from_engine(context.template.engine), |
| | 201 | ) |
| | 202 | ) |
| 186 | 203 | values = { |
| 187 | 204 | name: var.resolve(context) |
| 188 | 205 | for name, var in self.extra_context.items() |
| … |
… |
class IncludeNode(Node):
|
| 191 | 208 | return template.render(context.new(values)) |
| 192 | 209 | with context.push(**values): |
| 193 | 210 | return template.render(context) |
| | 211 | except DifferentTemplateEngineError: |
| | 212 | raise |
| 194 | 213 | except Exception as e: |
| 195 | 214 | if context.template.engine.debug: |
| 196 | 215 | raise |
diff --git a/django/template/utils.py b/django/template/utils.py
index fde2f64..fad3e90 100644
|
a
|
b
|
class EngineHandler:
|
| 87 | 87 | def all(self): |
| 88 | 88 | return [self[alias] for alias in self] |
| 89 | 89 | |
| | 90 | def get_name_from_engine(self, engine): |
| | 91 | try: |
| | 92 | return next(e.name for e in self.all() if e.engine is engine) |
| | 93 | except StopIteration: |
| | 94 | return 'unnamed' |
| | 95 | |
| 90 | 96 | |
| 91 | 97 | @functools.lru_cache() |
| 92 | 98 | def get_app_template_dirs(dirname): |
diff --git a/tests/template_tests/syntax_tests/test_include.py b/tests/template_tests/syntax_tests/test_include.py
index 2b08f3f..28b20e0 100644
|
a
|
b
|
import warnings
|
| 3 | 3 | from django.template import ( |
| 4 | 4 | Context, Engine, TemplateDoesNotExist, TemplateSyntaxError, loader, |
| 5 | 5 | ) |
| | 6 | from django.template.loader_tags import DifferentTemplateEngineError |
| 6 | 7 | from django.test import SimpleTestCase, ignore_warnings |
| 7 | 8 | from django.utils.deprecation import RemovedInDjango21Warning |
| 8 | 9 | |
| … |
… |
class IncludeTests(SimpleTestCase):
|
| 282 | 283 | output = tmpl.render({'tmpl': loader.get_template('index.html')}) |
| 283 | 284 | self.assertEqual(output, 'index\n\n') |
| 284 | 285 | |
| | 286 | def test_include_from_other_engine(self): |
| | 287 | engine = Engine() |
| | 288 | ctx = Context({'tmpl': loader.get_template('index.html')}) |
| | 289 | outer_tmpl = engine.from_string('{% include tmpl %}') |
| | 290 | msg = ( |
| | 291 | "Included template 'index.html' is from engine 'django' but parent " |
| | 292 | "template None is from engine 'unnamed'. Including a template from " |
| | 293 | "a different engine is prohibited." |
| | 294 | ) |
| | 295 | with self.assertRaisesMessage(DifferentTemplateEngineError, msg): |
| | 296 | outer_tmpl.render(ctx) |
| | 297 | |
| 285 | 298 | def test_include_immediate_missing(self): |
| 286 | 299 | """ |
| 287 | 300 | #16417 -- Include tags pointing to missing templates should not raise |