2005-10-15 06:22:12 +08:00
# Wrapper for loading templates from storage of some sort (e.g. filesystem, database).
#
# This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use.
# Each loader is expected to have this interface:
#
# callable(name, dirs=[])
#
# name is the template name.
# dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
#
2005-11-24 07:10:17 +08:00
# The loader should return a tuple of (template_source, path). The path returned
# might be shown to the user for debugging purposes, so it should identify where
# the template was loaded from.
#
2005-10-15 06:22:12 +08:00
# Each loader should have an "is_usable" attribute set. This is a boolean that
# specifies whether the loader can be used in this Python installation. Each
# loader is responsible for setting this when it's initialized.
#
# For example, the eggs loader (which is capable of loading templates from
# Python eggs) sets is_usable to False if the "pkg_resources" module isn't
# installed, because pkg_resources is necessary to read eggs.
2005-10-15 04:10:13 +08:00
2005-10-15 06:22:12 +08:00
from django . core . exceptions import ImproperlyConfigured
2006-07-22 04:39:17 +08:00
from django . template import Origin , Template , Context , TemplateDoesNotExist , add_to_builtins
2006-05-02 09:31:56 +08:00
from django . conf import settings
2005-10-15 06:22:12 +08:00
2006-02-02 13:07:12 +08:00
template_source_loaders = None
2005-10-15 06:22:12 +08:00
2005-11-24 07:10:17 +08:00
class LoaderOrigin ( Origin ) :
def __init__ ( self , display_name , loader , name , dirs ) :
super ( LoaderOrigin , self ) . __init__ ( display_name )
self . loader , self . loadname , self . dirs = loader , name , dirs
def reload ( self ) :
return self . loader ( self . loadname , self . dirs ) [ 0 ]
def make_origin ( display_name , loader , name , dirs ) :
2006-05-02 09:31:56 +08:00
if settings . TEMPLATE_DEBUG :
2005-11-24 07:10:17 +08:00
return LoaderOrigin ( display_name , loader , name , dirs )
else :
return None
def find_template_source ( name , dirs = None ) :
2006-02-02 13:07:12 +08:00
# Calculate template_source_loaders the first time the function is executed
# because putting this logic in the module-level namespace may cause
# circular import errors. See Django ticket #1292.
global template_source_loaders
if template_source_loaders is None :
2008-05-29 20:40:25 +08:00
loaders = [ ]
2006-05-02 09:31:56 +08:00
for path in settings . TEMPLATE_LOADERS :
2006-02-02 13:07:12 +08:00
i = path . rfind ( ' . ' )
module , attr = path [ : i ] , path [ i + 1 : ]
try :
mod = __import__ ( module , globals ( ) , locals ( ) , [ attr ] )
except ImportError , e :
raise ImproperlyConfigured , ' Error importing template source loader %s : " %s " ' % ( module , e )
try :
func = getattr ( mod , attr )
except AttributeError :
raise ImproperlyConfigured , ' Module " %s " does not define a " %s " callable template source loader ' % ( module , attr )
if not func . is_usable :
import warnings
warnings . warn ( " Your TEMPLATE_LOADERS setting includes %r , but your Python installation doesn ' t support that type of template loading. Consider removing that line from TEMPLATE_LOADERS. " % path )
else :
2008-05-29 20:40:25 +08:00
loaders . append ( func )
template_source_loaders = tuple ( loaders )
2005-10-15 06:22:12 +08:00
for loader in template_source_loaders :
try :
2005-11-25 05:14:42 +08:00
source , display_name = loader ( name , dirs )
2005-11-24 07:10:17 +08:00
return ( source , make_origin ( display_name , loader , name , dirs ) )
2005-10-15 06:29:13 +08:00
except TemplateDoesNotExist :
2005-10-15 06:22:12 +08:00
pass
2005-10-15 06:29:13 +08:00
raise TemplateDoesNotExist , name
2005-10-15 04:10:13 +08:00
def get_template ( template_name ) :
"""
Returns a compiled Template object for the given template name ,
handling template inheritance recursively .
"""
2006-09-02 17:26:24 +08:00
source , origin = find_template_source ( template_name )
template = get_template_from_string ( source , origin , template_name )
return template
2005-10-15 04:10:13 +08:00
2006-09-02 17:26:24 +08:00
def get_template_from_string ( source , origin = None , name = None ) :
2005-10-15 04:10:13 +08:00
"""
Returns a compiled Template object for the given template code ,
handling template inheritance recursively .
"""
2006-09-02 17:26:24 +08:00
return Template ( source , origin , name )
2005-10-15 04:10:13 +08:00
2007-06-22 15:15:04 +08:00
def render_to_string ( template_name , dictionary = None , context_instance = None ) :
2005-10-15 04:10:13 +08:00
"""
2007-06-22 15:15:04 +08:00
Loads the given template_name and renders it with the given dictionary as
context . The template_name may be a string to load a single template using
get_template , or it may be a tuple to use select_template to find one of
the templates in the list . Returns a string .
2005-10-15 04:10:13 +08:00
"""
2007-06-22 15:15:04 +08:00
dictionary = dictionary or { }
2005-10-15 04:10:13 +08:00
if isinstance ( template_name , ( list , tuple ) ) :
t = select_template ( template_name )
else :
t = get_template ( template_name )
if context_instance :
context_instance . update ( dictionary )
else :
context_instance = Context ( dictionary )
2007-06-22 15:15:04 +08:00
return t . render ( context_instance )
2005-10-15 04:10:13 +08:00
def select_template ( template_name_list ) :
" Given a list of template names, returns the first that can be loaded. "
for template_name in template_name_list :
try :
return get_template ( template_name )
except TemplateDoesNotExist :
continue
# If we get here, none of the templates could be loaded
raise TemplateDoesNotExist , ' , ' . join ( template_name_list )
2006-05-02 09:31:56 +08:00
add_to_builtins ( ' django.template.loader_tags ' )