Kaydet (Commit) 80d6b6b8 authored tarafından Preston Timmons's avatar Preston Timmons Kaydeden (comit) Tim Graham

Fixed #24409 -- Combined the app_directories and filesystem loader implementation.

Besides the directories they look in, these two loaders are functionally
the same. This removes unnecessary code duplication between the two.
üst 4b8979e4
......@@ -3,39 +3,12 @@ Wrapper for loading templates from "templates" directories in INSTALLED_APPS
packages.
"""
import io
from django.core.exceptions import SuspiciousFileOperation
from django.template.base import TemplateDoesNotExist
from django.template.utils import get_app_template_dirs
from django.utils._os import safe_join
from .base import Loader as BaseLoader
from .filesystem import Loader as FilesystemLoader
class Loader(BaseLoader):
def get_template_sources(self, template_name, template_dirs=None):
"""
Returns the absolute paths to "template_name", when appended to each
directory in "template_dirs". Any paths that don't lie inside one of the
template dirs are excluded from the result set, for security reasons.
"""
if not template_dirs:
template_dirs = get_app_template_dirs('templates')
for template_dir in template_dirs:
try:
yield safe_join(template_dir, template_name)
except SuspiciousFileOperation:
# The joined path was located outside of this template_dir
# (it might be inside another one, so this isn't fatal).
pass
class Loader(FilesystemLoader):
def load_template_source(self, template_name, template_dirs=None):
for filepath in self.get_template_sources(template_name, template_dirs):
try:
with io.open(filepath, encoding=self.engine.file_charset) as fp:
return fp.read(), filepath
except IOError:
pass
raise TemplateDoesNotExist(template_name)
def get_dirs(self):
return get_app_template_dirs('templates')
......@@ -13,6 +13,9 @@ from .base import Loader as BaseLoader
class Loader(BaseLoader):
def get_dirs(self):
return self.engine.dirs
def get_template_sources(self, template_name, template_dirs=None):
"""
Returns the absolute paths to "template_name", when appended to each
......@@ -20,7 +23,7 @@ class Loader(BaseLoader):
template dirs are excluded from the result set, for security reasons.
"""
if not template_dirs:
template_dirs = self.engine.dirs
template_dirs = self.get_dirs()
for template_dir in template_dirs:
try:
yield safe_join(template_dir, template_name)
......@@ -30,16 +33,10 @@ class Loader(BaseLoader):
pass
def load_template_source(self, template_name, template_dirs=None):
tried = []
for filepath in self.get_template_sources(template_name, template_dirs):
try:
with io.open(filepath, encoding=self.engine.file_charset) as fp:
return fp.read(), filepath
except IOError:
tried.append(filepath)
if tried:
error_msg = "Tried %s" % tried
else:
error_msg = ("Your template directories configuration is empty. "
"Change it to point to at least one template directory.")
raise TemplateDoesNotExist(error_msg)
pass
raise TemplateDoesNotExist(template_name)
......@@ -185,11 +185,16 @@ class FileSystemLoaderTests(SimpleTestCase):
def check_sources(path, expected_sources):
expected_sources = [os.path.abspath(s) for s in expected_sources]
self.assertEqual(
list(loader.get_template_sources(path, dirs)),
list(loader.get_template_sources(path)),
expected_sources,
)
yield check_sources
original_dirs = self.engine.dirs
self.engine.dirs = dirs
try:
yield check_sources
finally:
self.engine.dirs = original_dirs
def test_directory_security(self):
with self.source_checker(['/dir1', '/dir2']) as check_sources:
......@@ -234,9 +239,18 @@ class FileSystemLoaderTests(SimpleTestCase):
check_sources('/DIR1/index.HTML', ['/DIR1/index.HTML'])
class AppDirectoriesLoaderTest(FileSystemLoaderTests):
class AppDirectoriesLoaderTest(SimpleTestCase):
def setUp(self):
self.engine = Engine(
loaders=['django.template.loaders.app_directories.Loader'],
)
@override_settings(INSTALLED_APPS=['template_tests'])
def test_load_template(self):
self.engine.get_template('index.html')
@override_settings(INSTALLED_APPS=[])
def test_not_installed(self):
with self.assertRaises(TemplateDoesNotExist):
self.engine.get_template('index.html')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment