Commit d58597a7 authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

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.
parent cd7146de
Loading
Loading
Loading
Loading
+2 −24
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
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)
+3 −3
Original line number Diff line number Diff line
@@ -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 = {}