Refactored listing template subdirectories in apps.

This change has the nice side effect of removing code that ran at import
time and depended on the app registry at module level -- a notorious
cause of AppRegistryNotReady exceptions.
This commit is contained in:
Aymeric Augustin 2014-11-10 21:04:04 +01:00
parent cd7146debe
commit d58597a7b8
3 changed files with 34 additions and 27 deletions

View File

@ -4,38 +4,16 @@ packages.
"""
import io
import os
import sys
from django.apps import apps
from django.conf import settings
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 django.utils import six
from .base import Loader as BaseLoader
def calculate_app_template_dirs():
if six.PY2:
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
app_template_dirs = []
for app_config in apps.get_app_configs():
if not app_config.path:
continue
template_dir = os.path.join(app_config.path, 'templates')
if os.path.isdir(template_dir):
if six.PY2:
template_dir = template_dir.decode(fs_encoding)
app_template_dirs.append(template_dir)
return tuple(app_template_dirs)
# At compile time, cache the directories to search.
app_template_dirs = calculate_app_template_dirs()
class Loader(BaseLoader):
is_usable = True
@ -46,7 +24,7 @@ class Loader(BaseLoader):
template dirs are excluded from the result set, for security reasons.
"""
if not template_dirs:
template_dirs = app_template_dirs
template_dirs = get_app_template_dirs('templates')
for template_dir in template_dirs:
try:
yield safe_join(template_dir, template_name)

29
django/template/utils.py Normal file
View File

@ -0,0 +1,29 @@
import os
import sys
from django.apps import apps
from django.utils import lru_cache
from django.utils import six
@lru_cache.lru_cache()
def get_app_template_dirs(dirname):
"""
Return an iterable of paths of directories to load app templates from.
dirname is the name of the subdirectory containing templates inside
installed applications.
"""
if six.PY2:
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
template_dirs = []
for app_config in apps.get_app_configs():
if not app_config.path:
continue
template_dir = os.path.join(app_config.path, dirname)
if os.path.isdir(template_dir):
if six.PY2:
template_dir = template_dir.decode(fs_encoding)
template_dirs.append(template_dir)
# Immutable return value because it will be cached and shared by callers.
return tuple(template_dirs)

View File

@ -39,9 +39,9 @@ def update_installed_apps(**kwargs):
# Rebuild templatetags module cache.
from django.template import base as mod
mod.templatetags_modules = []
# Rebuild app_template_dirs cache.
from django.template.loaders import app_directories as mod
mod.app_template_dirs = mod.calculate_app_template_dirs()
# Rebuild get_app_template_dirs cache.
from django.template.utils import get_app_template_dirs
get_app_template_dirs.cache_clear()
# Rebuild translations cache.
from django.utils.translation import trans_real
trans_real._translations = {}