Moved all template loaders under django.template.loaders.
Reformatted the code of base.Loader according to modern standards. Turned the test template loader into a regular locmem.Loader -- but didn't document it. Added a normal deprecation path for BaseLoader which is a public API. Added an accelerated deprecation path for TestTemplateLoader which is a private API.
This commit is contained in:
parent
cffa559082
commit
2577ae6a08
|
@ -25,54 +25,18 @@
|
|||
# Python eggs) sets is_usable to False if the "pkg_resources" module isn't
|
||||
# installed, because pkg_resources is necessary to read eggs.
|
||||
|
||||
import warnings
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.template.base import Origin, Template, Context, TemplateDoesNotExist
|
||||
from django.conf import settings
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils import six
|
||||
|
||||
template_source_loaders = None
|
||||
|
||||
|
||||
class BaseLoader(object):
|
||||
is_usable = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def __call__(self, template_name, template_dirs=None):
|
||||
return self.load_template(template_name, template_dirs)
|
||||
|
||||
def load_template(self, template_name, template_dirs=None):
|
||||
source, display_name = self.load_template_source(template_name, template_dirs)
|
||||
origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
|
||||
try:
|
||||
template = get_template_from_string(source, origin, template_name)
|
||||
return template, None
|
||||
except TemplateDoesNotExist:
|
||||
# If compiling the template we found raises TemplateDoesNotExist, back off to
|
||||
# returning the source and display name for the template we were asked to load.
|
||||
# This allows for correct identification (later) of the actual template that does
|
||||
# not exist.
|
||||
return source, display_name
|
||||
|
||||
def load_template_source(self, template_name, template_dirs=None):
|
||||
"""
|
||||
Returns a tuple containing the source and origin for the given template
|
||||
name.
|
||||
|
||||
"""
|
||||
raise NotImplementedError('subclasses of BaseLoader must provide a load_template_source() method')
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Resets any state maintained by the loader instance (e.g., cached
|
||||
templates or cached loader modules).
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class LoaderOrigin(Origin):
|
||||
def __init__(self, display_name, loader, name, dirs):
|
||||
super(LoaderOrigin, self).__init__(display_name)
|
||||
|
@ -199,3 +163,17 @@ def select_template(template_name_list, dirs=None):
|
|||
continue
|
||||
# If we get here, none of the templates could be loaded
|
||||
raise TemplateDoesNotExist(', '.join(not_found))
|
||||
|
||||
|
||||
# This line must remain at the bottom to avoid import loops.
|
||||
from .loaders import base
|
||||
|
||||
|
||||
class BaseLoader(base.Loader):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"django.template.loader.BaseLoader was renamed to "
|
||||
"django.template.loaders.base.Loader.",
|
||||
RemovedInDjango20Warning, stacklevel=2)
|
||||
super(BaseLoader, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -11,10 +11,11 @@ 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.loader import BaseLoader
|
||||
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:
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
from django.template.base import TemplateDoesNotExist
|
||||
from django.template.loader import get_template_from_string, make_origin
|
||||
|
||||
|
||||
class Loader(object):
|
||||
is_usable = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# XXX dropping arguments silently may not be the best idea.
|
||||
pass
|
||||
|
||||
def __call__(self, template_name, template_dirs=None):
|
||||
return self.load_template(template_name, template_dirs)
|
||||
|
||||
def load_template(self, template_name, template_dirs=None):
|
||||
source, display_name = self.load_template_source(
|
||||
template_name, template_dirs)
|
||||
origin = make_origin(
|
||||
display_name, self.load_template_source,
|
||||
template_name, template_dirs)
|
||||
|
||||
try:
|
||||
template = get_template_from_string(source, origin, template_name)
|
||||
except TemplateDoesNotExist:
|
||||
# If compiling the template we found raises TemplateDoesNotExist,
|
||||
# back off to returning the source and display name for the
|
||||
# template we were asked to load. This allows for correct
|
||||
# identification of the actual template that does not exist.
|
||||
return source, display_name
|
||||
else:
|
||||
return template, None
|
||||
|
||||
def load_template_source(self, template_name, template_dirs=None):
|
||||
"""
|
||||
Returns a tuple containing the source and origin for the given
|
||||
template name.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of Loader must provide "
|
||||
"a load_template_source() method")
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Resets any state maintained by the loader instance (e.g. cached
|
||||
templates or cached loader modules).
|
||||
"""
|
||||
pass
|
|
@ -5,9 +5,11 @@ to load templates from them in order, caching the result.
|
|||
|
||||
import hashlib
|
||||
from django.template.base import TemplateDoesNotExist
|
||||
from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin
|
||||
from django.template.loader import get_template_from_string, find_template_loader, make_origin
|
||||
from django.utils.encoding import force_bytes
|
||||
|
||||
from .base import Loader as BaseLoader
|
||||
|
||||
|
||||
class Loader(BaseLoader):
|
||||
is_usable = True
|
||||
|
|
|
@ -9,9 +9,10 @@ except ImportError:
|
|||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.template.base import TemplateDoesNotExist
|
||||
from django.template.loader import BaseLoader
|
||||
from django.utils import six
|
||||
|
||||
from .base import Loader as BaseLoader
|
||||
|
||||
|
||||
class Loader(BaseLoader):
|
||||
is_usable = resource_string is not None
|
||||
|
|
|
@ -7,9 +7,10 @@ import io
|
|||
from django.conf import settings
|
||||
from django.core.exceptions import SuspiciousFileOperation
|
||||
from django.template.base import TemplateDoesNotExist
|
||||
from django.template.loader import BaseLoader
|
||||
from django.utils._os import safe_join
|
||||
|
||||
from .base import Loader as BaseLoader
|
||||
|
||||
|
||||
class Loader(BaseLoader):
|
||||
is_usable = True
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
"""
|
||||
Wrapper for loading templates from a plain Python dict.
|
||||
"""
|
||||
|
||||
from django.template.base import TemplateDoesNotExist
|
||||
|
||||
from .base import Loader as BaseLoader
|
||||
|
||||
|
||||
class Loader(BaseLoader):
|
||||
is_usable = True
|
||||
|
||||
def __init__(self, templates_dict):
|
||||
self.templates_dict = templates_dict
|
||||
|
||||
def load_template_source(self, template_name, template_dirs=None,
|
||||
skip_template=None):
|
||||
try:
|
||||
return (self.templates_dict[template_name],
|
||||
"test:%s" % template_name)
|
||||
except KeyError:
|
||||
raise TemplateDoesNotExist(template_name)
|
|
@ -14,8 +14,8 @@ from django.core import mail
|
|||
from django.core.signals import request_started
|
||||
from django.db import reset_queries
|
||||
from django.http import request
|
||||
from django.template import Template, loader, TemplateDoesNotExist
|
||||
from django.template.loaders import cached
|
||||
from django.template import Template, loader
|
||||
from django.template.loaders import cached, locmem
|
||||
from django.test.signals import template_rendered, setting_changed
|
||||
from django.utils import six
|
||||
from django.utils.decorators import ContextDecorator
|
||||
|
@ -189,20 +189,14 @@ class override_template_loaders(ContextDecorator):
|
|||
delattr(loader, RESTORE_LOADERS_ATTR)
|
||||
|
||||
|
||||
class TestTemplateLoader(loader.BaseLoader):
|
||||
"A custom template loader that loads templates from a dictionary."
|
||||
is_usable = True
|
||||
class TestTemplateLoader(locmem.Loader):
|
||||
|
||||
def __init__(self, templates_dict):
|
||||
self.templates_dict = templates_dict
|
||||
|
||||
def load_template_source(self, template_name, template_dirs=None,
|
||||
skip_template=None):
|
||||
try:
|
||||
return (self.templates_dict[template_name],
|
||||
"test:%s" % template_name)
|
||||
except KeyError:
|
||||
raise TemplateDoesNotExist(template_name)
|
||||
def __init__(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"django.test.utils.TestTemplateLoader was renamed to "
|
||||
"django.template.loaders.locmem.Loader.",
|
||||
RemovedInDjango19Warning, stacklevel=2)
|
||||
super(TestTemplateLoader, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class override_with_test_loader(override_template_loaders):
|
||||
|
@ -238,11 +232,11 @@ class override_with_test_loader(override_template_loaders):
|
|||
@classmethod
|
||||
def _get_loader(cls, templates_dict, use_cached_loader=False):
|
||||
if use_cached_loader:
|
||||
loader = cached.Loader(['TestTemplateLoader'])
|
||||
loader._cached_loaders = [TestTemplateLoader(templates_dict)]
|
||||
loader = cached.Loader(['django.template.loaders.locmem.Loader'])
|
||||
loader._cached_loaders = [locmem.Loader(templates_dict)]
|
||||
return loader
|
||||
else:
|
||||
return TestTemplateLoader(templates_dict)
|
||||
return locmem.Loader(templates_dict)
|
||||
|
||||
|
||||
class override_settings(object):
|
||||
|
|
|
@ -82,6 +82,9 @@ details on these changes.
|
|||
* The backwards compatibility shim to allow ``FormMixin.get_form()`` to be
|
||||
defined with no default value for its ``form_class`` argument will be removed.
|
||||
|
||||
* The backwards compatibility alias ``django.template.loader.BaseLoader`` will
|
||||
be removed.
|
||||
|
||||
.. _deprecation-removed-in-1.9:
|
||||
|
||||
1.9
|
||||
|
|
|
@ -967,11 +967,16 @@ with the Django loading and rendering system!
|
|||
|
||||
The next step is to write a ``Loader`` class that returns instances of our custom
|
||||
template class instead of the default :class:`~django.template.Template`. Custom ``Loader``
|
||||
classes should inherit from ``django.template.loader.BaseLoader`` and override
|
||||
classes should inherit from ``django.template.loaders.base.Loader`` and override
|
||||
the ``load_template_source()`` method, which takes a ``template_name`` argument,
|
||||
loads the template from disk (or elsewhere), and returns a tuple:
|
||||
``(template_string, template_origin)``.
|
||||
|
||||
.. versionchanged:: 1.8
|
||||
|
||||
``django.template.loaders.base.Loader`` used to be defined at
|
||||
``django.template.loader.BaseLoader``.
|
||||
|
||||
The ``load_template()`` method of the ``Loader`` class retrieves the template
|
||||
string by calling ``load_template_source()``, instantiates a ``Template`` from
|
||||
the template source, and returns a tuple: ``(template, template_origin)``. Since
|
||||
|
|
|
@ -1029,6 +1029,13 @@ The decorators :func:`~django.test.override_settings` and
|
|||
class decorators. As a consequence, when overriding ``setUpClass()`` or
|
||||
``tearDownClass()``, the ``super`` implementation should always be called.
|
||||
|
||||
``django.template.loader.BaseLoader``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``django.template.loader.BaseLoader`` was renamed to
|
||||
``django.template.loaders.base.Loader``. If you've written a custom template
|
||||
loader that inherits ``BaseLoader``, you must inherit ``Loader`` instead.
|
||||
|
||||
.. removed-features-1.8:
|
||||
|
||||
Features removed in 1.8
|
||||
|
|
|
@ -221,7 +221,7 @@ class TemplateLoaderTests(TestCase):
|
|||
# We rely on the fact that runtests.py sets up TEMPLATE_DIRS to
|
||||
# point to a directory containing a login.html file. Also that
|
||||
# the file system and app directories loaders both inherit the
|
||||
# load_template method from the BaseLoader class, so we only need
|
||||
# load_template method from the base Loader class, so we only need
|
||||
# to test one of them.
|
||||
load_name = 'login.html'
|
||||
template = loader.get_template(load_name)
|
||||
|
@ -306,7 +306,7 @@ class TemplateLoaderTests(TestCase):
|
|||
def test_extends_include_missing_cachedloader(self):
|
||||
"""
|
||||
Same as test_extends_include_missing_baseloader, only tests
|
||||
behavior of the cached loader instead of BaseLoader.
|
||||
behavior of the cached loader instead of base loader.
|
||||
"""
|
||||
cache_loader = cached.Loader(('',))
|
||||
cache_loader._cached_loaders = (app_directories.Loader(),)
|
||||
|
|
Loading…
Reference in New Issue