comparison doc/loader.txt @ 902:09cc3627654c experimental-inline

Sync `experimental/inline` branch with [source:trunk@1126].
author cmlenz
date Fri, 23 Apr 2010 21:08:26 +0000
parents
children
comparison
equal deleted inserted replaced
830:de82830f8816 902:09cc3627654c
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
26 .. code-block:: python
27
28 from genshi.template import TemplateLoader
29
30 loader = TemplateLoader(['/path/to/dir1', '/path/to/dir2'],
31 auto_reload=True)
32 tmpl = loader.load('test.html')
33
34 When you try to load a template that can't be found, you get a
35 ``TemplateNotFound`` error.
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
39 ``TemplateLoader`` constructor), as well as on invocation of the ``load()``
40 method:
41
42 .. code-block:: python
43
44 from genshi.template.text import NewTextTemplate
45
46 tmpl = loader.load('mail.txt', cls=NewTextTemplate)
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.
61 Technically, this is a least-recently-used (LRU) cache, the default limit is
62 set to 25 templates.
63
64 Automatic Reloading
65 ===================
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
69 file are not taken into consideration as long as it is still found in the
70 cache. As this is inconvenient in development scenarios, the ``auto_reload``
71 option allows for automatic cache invalidation based on whether the template
72 source has changed.
73
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):
105 Translator(translations.ugettext).setup(template)
106
107 loader = TemplateLoader('templates', callback=template_loaded)
108
109 .. _`translation filter`: i18n.html
110
111 --------------------
112 Template Search Path
113 --------------------
114
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.
118
119 The order of the directories making up the search path is significant: the
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.
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
146 .. code-block:: python
147
148 from genshi.template import TemplateLoader, loader
149 tl = TemplateLoader([loader.directory('/path/to/dir/')])
150
151 That is the same as:
152
153 .. code-block:: python
154
155 tl = TemplateLoader(['/path/to/dir/'])
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
164 .. code-block:: python
165
166 from genshi.template import TemplateLoader, loader
167 tl = TemplateLoader([loader.package('myapp', 'templates')])
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
177 .. code-block:: python
178
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')
186
187 This example sets up a loader with three delegates, under the prefixes “core”,
188 “plugin1”, and “plugin2”. When a template is requested, the ``prefixed`` load
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
194 other delegates are not checked as their prefix does not match.
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``
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.
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
237 The protocol between the template loader and the ``Template`` class is simple
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
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.
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.
Copyright (C) 2012-2017 Edgewall Software