Login

Dynamic Template Loader

Author:
jgeewax
Posted:
July 3, 2008
Language:
Python
Version:
.96
Score:
1 (after 1 ratings)

This snippet provides support for dynamically importing templates. This helps you to avoid naming collisions and other problems.

The format is as follows:

  1. module.submodule.app:template.html
  2. module.submodule.app:subfolder/template.html
  3. module.submodule.app:/subfolder/template.html

Assuming the module is located in '/var/', these would map (respectively) to:

  1. /var/module/submodule/app/templates/template.html
  2. /var/module/submodule/app/templates/subfolder/template.html
  3. /var/module/submodule/app/templates/subfolder/template.html

The colon splits the the python module from the template directory, meaning you can import from anything that has a "templates" directory. This helps me to avoid naming collisions by specifying the application I'm referring to, without having to put long paths in my extends and include tags inside other templates. It's also dynamic in that if I move a library outside the old path, it has no effect on the templates.

To get this rolling, in your settings.py file, add the following::

TEMPLATE_LOADERS = ( 'addons.template_loader.load_template_source', # <--- add this 'django.template.loaders.app_directories.load_template_source', 'django.template.loaders.filesystem.load_template_source',

'django.template.loaders.eggs.load_template_source',

)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#---- addons/template_loader.py ----
"""
Wrapper for loading templates from "template" directories in arbitrary modules.
"""

import os

from django.conf import settings
from django.template import TemplateDoesNotExist
from addons import get_module_dir

def get_template_sources(template_name, template_dirs=None):
    delimiter = ':'
    
    if not delimiter in template_name: return []
    
    # Find the delimiter in the name and split by it
    i = template_name.find(delimiter)
    app, template_path = template_name[:i], template_name[i+1:]
    
    # Get the directory for the app and make sure that is indeed a directory
    app_dir = get_module_dir(app)
    parts = (app_dir, 'templates', template_path)
    
    # Normalize the path
    template_path = '/'.join(parts)
    
    # Return it as a list for iteration
    return [os.path.normpath(template_path)]

def load_template_source(template_name, template_dirs=None):
    for filepath in get_template_sources(template_name, template_dirs):
        try:
            return (open(filepath).read().decode(settings.FILE_CHARSET), filepath)
        except IOError:
            pass
    raise TemplateDoesNotExist, template_name
load_template_source.is_usable = True


#---- addons/util.py ----
import inspect
from os import path

def import_module(module_name):
    module = __import__(module_name, globals(), locals(), [], -1)    
    components =  module_name.split('.')
    for component in components[1:]:
        module = getattr(module, component)

    return module

def get_module_path(module_name):
    module = import_module(module_name)
    return inspect.getsourcefile(module)

def get_module_dir(module_name):
    return path.dirname(get_module_path(module_name))

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

Please login first before commenting.