883
|
1 .. -*- mode: rst; encoding: utf-8 -*-
|
|
2
|
|
3 =================
|
|
4 Loading Templates
|
|
5 =================
|
|
6
|
|
7 Genshi comes with a simple but flexible implementation of a template loader in
|
|
8 the ``genshi.template.loader`` module. The loader provides caching of
|
|
9 templates so they do not need to be reparsed when used, support for multiple
|
|
10 template directories that together form a virtual search path, as well as
|
|
11 support for different template loading strategies.
|
|
12
|
|
13 .. contents:: Contents
|
|
14 :depth: 3
|
|
15 .. sectnum::
|
|
16
|
|
17
|
|
18 -----
|
|
19 Usage
|
|
20 -----
|
|
21
|
|
22 The basic usage pattern is simple: instantiate one ``TemplateLoader`` object
|
|
23 and keep it around, then ask it to load a template whenever you need to load
|
|
24 one:
|
|
25
|
884
|
26 .. code-block:: python
|
883
|
27
|
884
|
28 from genshi.template import TemplateLoader
|
883
|
29
|
884
|
30 loader = TemplateLoader(['/path/to/dir1', '/path/to/dir2'],
|
|
31 auto_reload=True)
|
|
32 tmpl = loader.load('test.html')
|
883
|
33
|
|
34 When you try to load a template that can't be found, you get a
|
884
|
35 ``TemplateNotFound`` error.
|
883
|
36
|
|
37 The default template class used by the loader is ``MarkupTemplate``, but that
|
|
38 can be overridden both with a different default (as a keyword argument to the
|
884
|
39 ``TemplateLoader`` constructor), as well as on invocation of the ``load()``
|
|
40 method:
|
883
|
41
|
884
|
42 .. code-block:: python
|
883
|
43
|
884
|
44 from genshi.template.text import NewTextTemplate
|
|
45
|
|
46 tmpl = loader.load('mail.txt', cls=NewTextTemplate)
|
883
|
47
|
|
48
|
|
49 -------
|
|
50 Caching
|
|
51 -------
|
|
52
|
|
53 The ``TemplateLoader`` class provides a simple in-memory cache for parsed
|
|
54 template objects. This improves performance, because templates do not need to
|
|
55 be reparsed every time they are rendered.
|
|
56
|
|
57 The size of this cache can be adjusted using the `max_cache_size` option on
|
|
58 the ``TemplateLoader`` constructor. The value of that option determines the
|
|
59 maximum number of template objects kept in the cache. When this limit is
|
|
60 reached, any templates that haven't been used in a while get purged.
|
884
|
61 Technically, this is a least-recently-used (LRU) cache, the default limit is
|
|
62 set to 25 templates.
|
|
63
|
|
64 Automatic Reloading
|
|
65 ===================
|
883
|
66
|
|
67 Once a template has been cached, it will normally not get reparsed until it
|
|
68 has been purged from the cache. This means that any changes to the template
|
884
|
69 file are not taken into consideration as long as it is still found in the
|
883
|
70 cache. As this is inconvenient in development scenarios, the ``auto_reload``
|
|
71 option allows for automatic cache invalidation based on whether the template
|
884
|
72 source has changed.
|
883
|
73
|
884
|
74 .. code-block:: python
|
|
75
|
|
76 from genshi.template import TemplateLoader
|
|
77
|
|
78 loader = TemplateLoader('templates', auto_reload=True, max_cache_size=100)
|
|
79
|
|
80 In production environments, automatic reloading should be disabled, as it does
|
|
81 affect performance negatively.
|
|
82
|
|
83 Callback Interface
|
|
84 ==================
|
|
85
|
|
86 Sometimes you need to make sure that templates get properly configured after
|
|
87 they have been loaded, but you only want to do that when the template is
|
|
88 actually loaded and parsed, not when it is returned from the cache.
|
|
89
|
|
90 For such cases, the ``TemplateLoader`` provides a way to specify a callback
|
|
91 function that gets invoked whenever a template is loaded. You can specify that
|
|
92 callback by passing it into the loader constructor via the ``callback``
|
|
93 keyword argument, or later by setting the attribute of the same name. The
|
|
94 callback function should expect a single argument, the template object.
|
|
95
|
|
96 For example, to properly inject the `translation filter`_ into any loaded
|
|
97 template, you'd use code similar to this:
|
|
98
|
|
99 .. code-block:: python
|
|
100
|
|
101 from genshi.filters import Translator
|
|
102 from genshi.template import TemplateLoader
|
|
103
|
|
104 def template_loaded(template):
|
885
|
105 Translator(translations.ugettext).setup(template)
|
884
|
106
|
|
107 loader = TemplateLoader('templates', callback=template_loaded)
|
|
108
|
|
109 .. _`translation filter`: i18n.html
|
883
|
110
|
|
111 --------------------
|
|
112 Template Search Path
|
|
113 --------------------
|
|
114
|
884
|
115 The template loader can be configured with a list of multiple directories to
|
|
116 search for templates. The loader maps these directories to a single logical
|
|
117 directory for locating templates by file name.
|
883
|
118
|
|
119 The order of the directories making up the search path is significant: the
|
884
|
120 loader will first try to locate a requested template in the first directory on
|
|
121 the path, then in the second, and so on. If there are two templates with the
|
|
122 same file name in multiple directories on the search path, whatever file is
|
|
123 found first gets used.
|
883
|
124
|
|
125 Based on this design, an application could, for example, configure a search
|
|
126 path consisting of a directory containing the default templates, as well as a
|
|
127 directory where site-specific templates can be stored that will override the
|
|
128 default templates.
|
|
129
|
|
130
|
|
131 Load Functions
|
|
132 ==============
|
|
133
|
|
134 Usually the search path consists of strings representing directory paths, but
|
|
135 it may also contain “load functions”: functions that are basically invoked
|
|
136 with the file name, and return the template content.
|
|
137
|
|
138 Genshi comes with three builtin load functions:
|
|
139
|
|
140 ``directory(path)``
|
|
141 -------------------
|
|
142
|
|
143 The equivalent of just using a string containing the directory path: looks up
|
|
144 the file name in a specific directory.
|
|
145
|
884
|
146 .. code-block:: python
|
883
|
147
|
884
|
148 from genshi.template import TemplateLoader, loader
|
|
149 tl = TemplateLoader([loader.directory('/path/to/dir/')])
|
883
|
150
|
|
151 That is the same as:
|
|
152
|
884
|
153 .. code-block:: python
|
883
|
154
|
884
|
155 tl = TemplateLoader(['/path/to/dir/'])
|
883
|
156
|
|
157
|
|
158 ``package(name, path)``
|
|
159 -----------------------
|
|
160
|
|
161 Uses the ``pkg_resources`` API to locate files in Python package data (which
|
|
162 may be inside a ZIP archive).
|
|
163
|
884
|
164 .. code-block:: python
|
883
|
165
|
884
|
166 from genshi.template import TemplateLoader, loader
|
|
167 tl = TemplateLoader([loader.package('myapp', 'templates')])
|
883
|
168
|
|
169 This will look for templates in the ``templates`` directory of the Python
|
|
170 package ``myapp``.
|
|
171
|
|
172 ``prefixed(**delegates)``
|
|
173 -------------------------
|
|
174
|
|
175 Delegates load requests to different load functions based on the path prefix.
|
|
176
|
884
|
177 .. code-block:: python
|
883
|
178
|
884
|
179 from genshi.template import TemplateLoader, loader
|
|
180 tl = TemplateLoader(loader.prefixed(
|
|
181 core = '/tmp/dir1',
|
|
182 plugin1 = loader.package('plugin1', 'templates'),
|
|
183 plugin2 = loader.package('plugin2', 'templates'),
|
|
184 ))
|
|
185 tmpl = tl.load('core/index.html')
|
883
|
186
|
|
187 This example sets up a loader with three delegates, under the prefixes “core”,
|
884
|
188 “plugin1”, and “plugin2”. When a template is requested, the ``prefixed`` load
|
883
|
189 function looks for a delegate with a corresponding prefix, removes the prefix
|
|
190 from the path and asks the delegate to load the template.
|
|
191
|
|
192 In this case, assuming the directory ``/path/to/dir`` contains a file named
|
|
193 ``index.html``, that file will be used when we load ``core/index.html``. The
|
884
|
194 other delegates are not checked as their prefix does not match.
|
883
|
195
|
|
196
|
|
197 .. note:: These builtin load functions are available both as class methods
|
|
198 of the ``TemplateLoader`` class as well as on the module level
|
|
199
|
|
200
|
|
201 Custom Load Functions
|
|
202 ---------------------
|
|
203
|
|
204 You can easily use your own load function with the template loader, for
|
|
205 example to load templates from a database. All that is needed is a callable
|
|
206 object that accepts a ``filename`` (a string) and returns a tuple of the form
|
|
207 ``(filepath, filename, fileobj, uptodate_fun)``, where:
|
|
208
|
|
209 ``filepath``
|
884
|
210 is the absolute path to the template. This is primarily used for output in
|
|
211 tracebacks, and does not need to map to an actual path on the file system.
|
883
|
212 ``filename``
|
|
213 is the base name of the template file
|
|
214 ``fileobj``
|
|
215 is a readable file-like object that provides the content of the template
|
|
216 ``uptodate_fun``
|
|
217 is a function that the loader can invoke to check whether the cached version
|
|
218 of the template is still up-to-date, or ``None`` if the load function is not
|
|
219 able to provide such a check. If provided, the function should not expect
|
|
220 any parameters (so you'll definitely want to use a closure here), and should
|
|
221 return ``True`` if the template has not changed since it was last loaded.
|
|
222
|
|
223 When the requested template can not be found, the function should raise an
|
|
224 ``IOError`` or ``TemplateNotFound`` exception.
|
|
225
|
|
226
|
|
227 ------------------
|
|
228 Customized Loading
|
|
229 ------------------
|
|
230
|
|
231 If you require a completely different implementation of template loading, you
|
|
232 can extend or even replace the builtin ``TemplateLoader`` class.
|
|
233
|
|
234 Protocol
|
|
235 ========
|
|
236
|
884
|
237 The protocol between the template loader and the ``Template`` class is simple
|
883
|
238 and only used for processing includes. The only required part of that protocol
|
|
239 is that the object assigned to ``Template.loader`` implements a ``load``
|
|
240 method compatible to that of the ``TemplateLoader`` class, at the minimum with
|
|
241 the signature ``load(filename, relative_to=None, cls=None)``.
|
|
242
|
|
243 In addition, templates currently check for the existence and value of a boolean
|
890
|
244 ``auto_reload`` property. If the property does not exist or evaluates to a
|
|
245 non-truth value, inlining of included templates is disabled. Inlining is a
|
|
246 small optimization that removes some overhead in the processing of includes.
|
883
|
247
|
|
248 Subclassing ``TemplateLoader``
|
|
249 ==============================
|
|
250
|
|
251 You can also adjust the behavior of the ``TemplateLoader`` class by subclassing
|
|
252 it. You can of course override anything needed, but the class also provides the
|
|
253 ``_instantiate()`` hook, which is intended for use by subclasses to customize
|
|
254 the creation of the template object from the file name and content. Please
|
|
255 consult the code and the API documentation for more detail.
|