changeset 884:5a1c0ee0f659

Improve the template loader docs.
author cmlenz
date Fri, 16 Apr 2010 20:40:28 +0000
parents 0849dcc8ed46
children 80f80f2eec6a
files doc/i18n.txt doc/loader.txt doc/templates.txt
diffstat 3 files changed, 86 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/doc/i18n.txt
+++ b/doc/i18n.txt
@@ -205,7 +205,7 @@
       template.filters.insert(0, Translator(translations.ugettext))
   
   loader = TemplateLoader('templates', callback=template_loaded)
-  template = loader.load("...")
+  template = loader.load('test.html')
 
 This approach ensures that the filter is not added everytime the template is 
 loaded, and thus being applied multiple times.
--- a/doc/loader.txt
+++ b/doc/loader.txt
@@ -23,35 +23,27 @@
 and keep it around, then ask it to load a template whenever you need to load
 one:
 
-.. code-block:: pycon
+.. code-block:: python
 
-  >>> from genshi.template import TemplateLoader
+  from genshi.template import TemplateLoader
   
-  >>> loader = TemplateLoader(['/path/to/dir1', '/path/to/dir2'],
-  ...                         auto_reload=True)
-  >>> loader.load('test.html')
-  <MarkupTemplate "test.html">
+  loader = TemplateLoader(['/path/to/dir1', '/path/to/dir2'],
+                          auto_reload=True)
+  tmpl = loader.load('test.html')
 
 When you try to load a template that can't be found, you get a
-``TemplateNotFound`` error:
-
-.. code-block:: pycon
-
-  >>> loader.load('foobar.html')
-  Traceback (most recent call last):
-    ...
-  TemplateNotFound: Template "foobar.html" not found
+``TemplateNotFound`` error.
 
 The default template class used by the loader is ``MarkupTemplate``, but that
 can be overridden both with a different default (as a keyword argument to the
-``TemplateLoader`` constructor), as well as for every individual invocation of
-the ``load()`` method:
+``TemplateLoader`` constructor), as well as on invocation of the ``load()``
+method:
 
-.. code-block:: pycon
+.. code-block:: python
 
-  >>> from genshi.template.text import NewTextTemplate
-  >>> loader.load('mail.txt', cls=NewTextTemplate)
-  <NewTextTemplate "mail.txt">
+  from genshi.template.text import NewTextTemplate
+  
+  tmpl = loader.load('mail.txt', cls=NewTextTemplate)
 
 
 -------
@@ -66,29 +58,69 @@
 the ``TemplateLoader`` constructor. The value of that option determines the
 maximum number of template objects kept in the cache. When this limit is
 reached, any templates that haven't been used in a while get purged.
-Technically, this is a least-recently-used (LRU) cache.
+Technically, this is a least-recently-used (LRU) cache, the default limit is
+set to 25 templates.
+
+Automatic Reloading
+===================
 
 Once a template has been cached, it will normally not get reparsed until it
 has been purged from the cache. This means that any changes to the template
-files are not taken into consideration as long as it is still found in the
+file are not taken into consideration as long as it is still found in the
 cache. As this is inconvenient in development scenarios, the ``auto_reload``
 option allows for automatic cache invalidation based on whether the template
-source has changed. But in production environments, automatic reloading should
-be disabled, as it does affect performance negatively.
+source has changed.
 
+.. code-block:: python
+
+  from genshi.template import TemplateLoader
+  
+  loader = TemplateLoader('templates', auto_reload=True, max_cache_size=100)
+
+In production environments, automatic reloading should be disabled, as it does
+affect performance negatively.
+
+Callback Interface
+==================
+
+Sometimes you need to make sure that templates get properly configured after
+they have been loaded, but you only want to do that when the template is
+actually loaded and parsed, not when it is returned from the cache.
+
+For such cases, the ``TemplateLoader`` provides a way to specify a callback
+function that gets invoked whenever a template is loaded. You can specify that
+callback by passing it into the loader constructor via the ``callback``
+keyword argument, or later by setting the attribute of the same name. The
+callback function should expect a single argument, the template object.
+
+For example, to properly inject the `translation filter`_ into any loaded
+template, you'd use code similar to this:
+
+.. code-block:: python
+
+  from genshi.filters import Translator
+  from genshi.template import TemplateLoader
+  
+  def template_loaded(template):
+      template.filters.insert(0, Translator(translations.ugettext))
+  
+  loader = TemplateLoader('templates', callback=template_loaded)
+
+.. _`translation filter`: i18n.html
 
 --------------------
 Template Search Path
 --------------------
 
-The template loader can be configured with a list of multiple directories in
-which to search for templates. Taken together, these directories are mapped to
-a single logical directory for locating templates by file name.
+The template loader can be configured with a list of multiple directories to
+search for templates. The loader maps these directories to a single logical
+directory for locating templates by file name.
 
 The order of the directories making up the search path is significant: the
-loader will first try to locate a requested template in the first directory,
-then in the second, and so on. If there are two templates with the same file
-name in multiple directories on the search path, the file found first is used.
+loader will first try to locate a requested template in the first directory on
+the path, then in the second, and so on. If there are two templates with the
+same file name in multiple directories on the search path, whatever file is
+found first gets used.
 
 Based on this design, an application could, for example, configure a search
 path consisting of a directory containing the default templates, as well as a
@@ -111,16 +143,16 @@
 The equivalent of just using a string containing the directory path: looks up
 the file name in a specific directory.
 
-.. code-block:: pycon
+.. code-block:: python
 
-  >>> from genshi.template import TemplateLoader, loader
-  >>> tl = TemplateLoader([loader.directory('/path/to/dir/')])
+  from genshi.template import TemplateLoader, loader
+  tl = TemplateLoader([loader.directory('/path/to/dir/')])
 
 That is the same as:
 
-.. code-block:: pycon
+.. code-block:: python
 
-  >>> tl = TemplateLoader(['/path/to/dir/'])
+  tl = TemplateLoader(['/path/to/dir/'])
 
 
 ``package(name, path)``
@@ -129,10 +161,10 @@
 Uses the ``pkg_resources`` API to locate files in Python package data (which
 may be inside a ZIP archive).
 
-.. code-block:: pycon
+.. code-block:: python
 
-  >>> from genshi.template import TemplateLoader, loader
-  >>> tl = TemplateLoader([loader.package('myapp', 'templates')])
+  from genshi.template import TemplateLoader, loader
+  tl = TemplateLoader([loader.package('myapp', 'templates')])
 
 This will look for templates in the ``templates`` directory of the Python
 package ``myapp``.
@@ -142,25 +174,24 @@
 
 Delegates load requests to different load functions based on the path prefix.
 
-.. code-block:: pycon
+.. code-block:: python
 
-  >>> from genshi.template import TemplateLoader, loader
-  >>> tl = TemplateLoader(loader.prefixed(
-  ...   core = '/tmp/dir1',
-  ...   plugin1 = loader.package('plugin1', 'templates'),
-  ...   plugin2 = loader.package('plugin2', 'templates'),
-  ... ))
-  >>> tl.load('core/index.html')
-  <MarkupTemplate "core/index.html">
+  from genshi.template import TemplateLoader, loader
+  tl = TemplateLoader(loader.prefixed(
+    core = '/tmp/dir1',
+    plugin1 = loader.package('plugin1', 'templates'),
+    plugin2 = loader.package('plugin2', 'templates'),
+  ))
+  tmpl = tl.load('core/index.html')
 
 This example sets up a loader with three delegates, under the prefixes “core”,
-“plugin1”, and “plugin2”. When a template is requested the ``prefixed`` load
+“plugin1”, and “plugin2”. When a template is requested, the ``prefixed`` load
 function looks for a delegate with a corresponding prefix, removes the prefix
 from the path and asks the delegate to load the template.
 
 In this case, assuming the directory ``/path/to/dir`` contains a file named
 ``index.html``, that file will be used when we load ``core/index.html``. The
-other delegate are not checked as their prefix does not match.
+other delegates are not checked as their prefix does not match.
 
 
 .. note:: These builtin load functions are available both as class methods
@@ -176,7 +207,8 @@
 ``(filepath, filename, fileobj, uptodate_fun)``, where:
 
 ``filepath``
-  is the absolute path to the template
+  is the absolute path to the template. This is primarily used for output in
+  tracebacks, and does not need to map to an actual path on the file system.
 ``filename``
   is the base name of the template file
 ``fileobj``
@@ -202,7 +234,7 @@
 Protocol
 ========
 
-The protocol between the template loader and the templates itself is simple
+The protocol between the template loader and the ``Template`` class is simple
 and only used for processing includes. The only required part of that protocol
 is that the object assigned to ``Template.loader`` implements a ``load``
 method compatible to that of the ``TemplateLoader`` class, at the minimum with
--- a/doc/templates.txt
+++ b/doc/templates.txt
@@ -142,7 +142,7 @@
 .. _`Text Template Language`: text-templates.html
 .. _`Markup Streams`: streams.html
 
-Using a template loader provides the advantage that “compiled” templates are
+Using a `template loader`_ provides the advantage that “compiled” templates are
 automatically cached, and only parsed again when the template file changes. In
 addition, it enables the use of a *template search path*, allowing template
 directories to be spread across different file-system locations. Using a
@@ -159,6 +159,7 @@
 See the `API documentation <api/index.html>`_ for details on using Genshi via
 the Python API.
 
+.. _`template loader`: loader.html
 
 .. _`expressions`:
 
Copyright (C) 2012-2017 Edgewall Software