Fixed #6587 -- Removed nasty __path__ hacking in templatetag loading. Thanks to Øyvind Satvik and Andrew Badr for their work on this patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12295 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2010-01-26 01:38:50 +00:00
parent 9cd1d6ed87
commit 12d3799dd2
5 changed files with 73 additions and 28 deletions

View File

@ -309,12 +309,17 @@ def missing_docutils_page(request):
def load_all_installed_template_libraries(): def load_all_installed_template_libraries():
# Load/register all template tag libraries from installed apps. # Load/register all template tag libraries from installed apps.
for e in templatetags.__path__: for module_name in template.get_templatetags_modules():
libraries = [os.path.splitext(p)[0] for p in os.listdir(e) if p.endswith('.py') and p[0].isalpha()] mod = import_module(module_name)
libraries = [
os.path.splitext(p)[0]
for p in os.listdir(os.path.dirname(mod.__file__))
if p.endswith('.py') and p[0].isalpha()
]
for library_name in libraries: for library_name in libraries:
try: try:
lib = template.get_library("django.templatetags.%s" % library_name.split('.')[-1]) lib = template.get_library(library_name)
except template.InvalidTemplateLibrary: except template.InvalidTemplateLibrary, e:
pass pass
def get_return_data_type(func_name): def get_return_data_type(func_name):

View File

@ -809,7 +809,7 @@ class TextNode(Node):
def render(self, context): def render(self, context):
return self.s return self.s
def _render_value_in_context(value, context): def _render_value_in_context(value, context):
""" """
Converts any value to a string to become part of a rendered template. This Converts any value to a string to become part of a rendered template. This
@ -966,22 +966,70 @@ class Library(object):
return func return func
return dec return dec
def get_library(module_name): def import_library(taglib_module):
lib = libraries.get(module_name, None) """Load a template tag library module.
Verifies that the library contains a 'register' attribute, and
returns that attribute as the representation of the library
"""
try:
mod = import_module(taglib_module)
except ImportError:
return None
try:
return mod.register
except AttributeError:
raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % taglib_module)
templatetags_modules = []
def get_templatetags_modules():
"""Return the list of all available template tag modules.
Caches the result for faster access.
"""
global templatetags_modules
if not templatetags_modules:
_templatetags_modules = []
# Populate list once per thread.
for app_module in ['django'] + list(settings.INSTALLED_APPS):
try:
templatetag_module = '%s.templatetags' % app_module
import_module(templatetag_module)
_templatetags_modules.append(templatetag_module)
except ImportError:
continue
templatetags_modules = _templatetags_modules
return templatetags_modules
def get_library(library_name):
"""
Load the template library module with the given name.
If library is not already loaded loop over all templatetags modules to locate it.
{% load somelib %} and {% load someotherlib %} loops twice.
Subsequent loads eg. {% load somelib %} in the same process will grab the cached
module from libraries.
"""
lib = libraries.get(library_name, None)
if not lib: if not lib:
try: templatetags_modules = get_templatetags_modules()
mod = import_module(module_name) tried_modules = []
except ImportError, e: for module in templatetags_modules:
raise InvalidTemplateLibrary("Could not load template library from %s, %s" % (module_name, e)) taglib_module = '%s.%s' % (module, library_name)
try: tried_modules.append(taglib_module)
lib = mod.register lib = import_library(taglib_module)
libraries[module_name] = lib if lib:
except AttributeError: libraries[library_name] = lib
raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % module_name) break
if not lib:
raise InvalidTemplateLibrary("Template library %s not found, tried %s" % (library_name, ','.join(tried_modules)))
return lib return lib
def add_to_builtins(module_name): def add_to_builtins(module):
builtins.append(get_library(module_name)) builtins.append(import_library(module))
add_to_builtins('django.template.defaulttags') add_to_builtins('django.template.defaulttags')
add_to_builtins('django.template.defaultfilters') add_to_builtins('django.template.defaultfilters')

View File

@ -920,7 +920,7 @@ def load(parser, token):
for taglib in bits[1:]: for taglib in bits[1:]:
# add the library to the parser # add the library to the parser
try: try:
lib = get_library("django.templatetags.%s" % taglib) lib = get_library(taglib)
parser.add_library(lib) parser.add_library(lib)
except InvalidTemplateLibrary, e: except InvalidTemplateLibrary, e:
raise TemplateSyntaxError("'%s' is not a valid tag library: %s" % raise TemplateSyntaxError("'%s' is not a valid tag library: %s" %

View File

@ -1,8 +0,0 @@
from django.conf import settings
from django.utils import importlib
for a in settings.INSTALLED_APPS:
try:
__path__.extend(importlib.import_module('.templatetags', a).__path__)
except ImportError:
pass

View File

@ -59,7 +59,7 @@ def do_echo(parser, token):
register.tag("echo", do_echo) register.tag("echo", do_echo)
template.libraries['django.templatetags.testtags'] = register template.libraries['testtags'] = register
##################################### #####################################
# Helper objects for template tests # # Helper objects for template tests #