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 ...@@ -3,39 +3,12 @@ Wrapper for loading templates from "templates" directories in INSTALLED_APPS
packages. 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.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): class Loader(FilesystemLoader):
"""
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
def load_template_source(self, template_name, template_dirs=None): def get_dirs(self):
for filepath in self.get_template_sources(template_name, template_dirs): return get_app_template_dirs('templates')
try:
with io.open(filepath, encoding=self.engine.file_charset) as fp:
return fp.read(), filepath
except IOError:
pass
raise TemplateDoesNotExist(template_name)
...@@ -13,6 +13,9 @@ from .base import Loader as BaseLoader ...@@ -13,6 +13,9 @@ from .base import Loader as BaseLoader
class Loader(BaseLoader): class Loader(BaseLoader):
def get_dirs(self):
return self.engine.dirs
def get_template_sources(self, template_name, template_dirs=None): def get_template_sources(self, template_name, template_dirs=None):
""" """
Returns the absolute paths to "template_name", when appended to each Returns the absolute paths to "template_name", when appended to each
...@@ -20,7 +23,7 @@ class Loader(BaseLoader): ...@@ -20,7 +23,7 @@ class Loader(BaseLoader):
template dirs are excluded from the result set, for security reasons. template dirs are excluded from the result set, for security reasons.
""" """
if not template_dirs: if not template_dirs:
template_dirs = self.engine.dirs template_dirs = self.get_dirs()
for template_dir in template_dirs: for template_dir in template_dirs:
try: try:
yield safe_join(template_dir, template_name) yield safe_join(template_dir, template_name)
...@@ -30,16 +33,10 @@ class Loader(BaseLoader): ...@@ -30,16 +33,10 @@ class Loader(BaseLoader):
pass pass
def load_template_source(self, template_name, template_dirs=None): def load_template_source(self, template_name, template_dirs=None):
tried = []
for filepath in self.get_template_sources(template_name, template_dirs): for filepath in self.get_template_sources(template_name, template_dirs):
try: try:
with io.open(filepath, encoding=self.engine.file_charset) as fp: with io.open(filepath, encoding=self.engine.file_charset) as fp:
return fp.read(), filepath return fp.read(), filepath
except IOError: except IOError:
tried.append(filepath) pass
if tried: raise TemplateDoesNotExist(template_name)
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)
...@@ -185,11 +185,16 @@ class FileSystemLoaderTests(SimpleTestCase): ...@@ -185,11 +185,16 @@ class FileSystemLoaderTests(SimpleTestCase):
def check_sources(path, expected_sources): def check_sources(path, expected_sources):
expected_sources = [os.path.abspath(s) for s in expected_sources] expected_sources = [os.path.abspath(s) for s in expected_sources]
self.assertEqual( self.assertEqual(
list(loader.get_template_sources(path, dirs)), list(loader.get_template_sources(path)),
expected_sources, 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): def test_directory_security(self):
with self.source_checker(['/dir1', '/dir2']) as check_sources: with self.source_checker(['/dir1', '/dir2']) as check_sources:
...@@ -234,9 +239,18 @@ class FileSystemLoaderTests(SimpleTestCase): ...@@ -234,9 +239,18 @@ class FileSystemLoaderTests(SimpleTestCase):
check_sources('/DIR1/index.HTML', ['/DIR1/index.HTML']) check_sources('/DIR1/index.HTML', ['/DIR1/index.HTML'])
class AppDirectoriesLoaderTest(FileSystemLoaderTests): class AppDirectoriesLoaderTest(SimpleTestCase):
def setUp(self): def setUp(self):
self.engine = Engine( self.engine = Engine(
loaders=['django.template.loaders.app_directories.Loader'], 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