Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 1 | .. _jinja-extensions: |
| 2 | |
| 3 | Extensions |
| 4 | ========== |
| 5 | |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 6 | Jinja2 supports extensions that can add extra filters, tests, globals or even |
| 7 | extend the parser. The main motivation of extensions is it to move often used |
| 8 | code into a reusable class like adding support for internationalization. |
| 9 | |
| 10 | |
| 11 | Adding Extensions |
| 12 | ----------------- |
| 13 | |
| 14 | Extensions are added to the Jinja2 environment at creation time. Once the |
| 15 | environment is created additional extensions cannot be added. To add an |
| 16 | extension pass a list of extension classes or import paths to the |
| 17 | `environment` parameter of the :class:`Environment` constructor. The following |
| 18 | example creates a Jinja2 environment with the i18n extension loaded:: |
| 19 | |
Armin Ronacher | 09c002e | 2008-05-10 22:21:30 +0200 | [diff] [blame] | 20 | jinja_env = Environment(extensions=['jinja2.ext.i18n']) |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 21 | |
| 22 | |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 23 | .. _i18n-extension: |
| 24 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 25 | i18n Extension |
| 26 | -------------- |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 27 | |
Armin Ronacher | 5d2733f | 2008-05-15 23:26:52 +0200 | [diff] [blame] | 28 | **Import name:** `jinja2.ext.i18n` |
| 29 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 30 | Jinja2 currently comes with one extension, the i18n extension. It can be |
| 31 | used in combination with `gettext`_ or `babel`_. If the i18n extension is |
| 32 | enabled Jinja2 provides a `trans` statement that marks the wrapped string as |
| 33 | translatable and calls `gettext`. |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 34 | |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 35 | After enabling dummy `_` function that forwards calls to `gettext` is added |
| 36 | to the environment globals. An internationalized application then has to |
| 37 | provide at least an `gettext` and optoinally a `ngettext` function into the |
| 38 | namespace. Either globally or for each rendering. |
| 39 | |
| 40 | After enabling of the extension the environment provides the following |
| 41 | additional methods: |
| 42 | |
| 43 | .. method:: jinja2.Environment.install_gettext_translations(translations) |
| 44 | |
| 45 | Installs a translation globally for that environment. The tranlations |
| 46 | object provided must implement at least `ugettext` and `ungettext`. |
| 47 | The `gettext.NullTranslations` and `gettext.GNUTranslations` classes |
| 48 | as well as `Babel`_\s `Translations` class are supported. |
| 49 | |
| 50 | .. method:: jinja2.Environment.install_null_translations() |
| 51 | |
| 52 | Install dummy gettext functions. This is useful if you want to prepare |
| 53 | the application for internationalization but don't want to implement the |
| 54 | full internationalization system yet. |
| 55 | |
| 56 | .. method:: jinja2.Environment.uninstall_gettext_translations() |
| 57 | |
| 58 | Uninstall the translations again. |
| 59 | |
| 60 | .. method:: jinja2.Environment.extract_translations(source) |
| 61 | |
| 62 | Extract localizable strings from the given template node or source. |
| 63 | |
| 64 | For every string found this function yields a ``(lineno, function, |
| 65 | message)`` tuple, where: |
| 66 | |
| 67 | * `lineno` is the number of the line on which the string was found, |
| 68 | * `function` is the name of the `gettext` function used (if the |
| 69 | string was extracted from embedded Python code), and |
| 70 | * `message` is the string itself (a `unicode` object, or a tuple |
| 71 | of `unicode` objects for functions with multiple string arguments). |
| 72 | |
| 73 | If `Babel`_ is installed :ref:`the babel integration <babel-integration>` |
| 74 | can be used to extract strings for babel. |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 75 | |
| 76 | For a web application that is available in multiple languages but gives all |
| 77 | the users the same language (for example a multilingual forum software |
| 78 | installed for a French community) may load the translations once and add the |
| 79 | translation methods to the environment at environment generation time:: |
| 80 | |
| 81 | translations = get_gettext_translations() |
Armin Ronacher | 2b22874 | 2008-05-18 20:29:32 +0200 | [diff] [blame] | 82 | env = Environment(extensions=['jinja2.ext.i18n']) |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 83 | env.install_gettext_translations(translations) |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 84 | |
| 85 | The `get_gettext_translations` function would return the translator for the |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 86 | current configuration. (For example by using `gettext.find`) |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 87 | |
| 88 | The usage of the `i18n` extension for template designers is covered as part |
| 89 | :ref:`of the template documentation <i18n-in-templates>`. |
| 90 | |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 91 | .. _gettext: http://docs.python.org/dev/library/gettext |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 92 | .. _Babel: http://babel.edgewall.org/ |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 93 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 94 | |
Armin Ronacher | 6df604e | 2008-05-23 22:18:38 +0200 | [diff] [blame] | 95 | Expression Statement |
| 96 | -------------------- |
Armin Ronacher | 5d2733f | 2008-05-15 23:26:52 +0200 | [diff] [blame] | 97 | |
| 98 | **Import name:** `jinja2.ext.do` |
| 99 | |
Armin Ronacher | 6df604e | 2008-05-23 22:18:38 +0200 | [diff] [blame] | 100 | The "do" aka expression-statement extension adds a simple `do` tag to the |
Armin Ronacher | 5d2733f | 2008-05-15 23:26:52 +0200 | [diff] [blame] | 101 | template engine that works like a variable expression but ignores the |
| 102 | return value. |
| 103 | |
Armin Ronacher | 3da9031 | 2008-05-23 16:37:28 +0200 | [diff] [blame] | 104 | .. _loopcontrols-extension: |
| 105 | |
Armin Ronacher | 6df604e | 2008-05-23 22:18:38 +0200 | [diff] [blame] | 106 | Loop Controls |
| 107 | ------------- |
Armin Ronacher | 3da9031 | 2008-05-23 16:37:28 +0200 | [diff] [blame] | 108 | |
| 109 | **Import name:** `jinja2.ext.loopcontrols` |
| 110 | |
| 111 | This extension adds support for `break` and `continue` in loops. After |
| 112 | enabling Jinja2 provides those two keywords which work exactly like in |
| 113 | Python. |
| 114 | |
Armin Ronacher | 5d2733f | 2008-05-15 23:26:52 +0200 | [diff] [blame] | 115 | |
Armin Ronacher | ed98cac | 2008-05-07 08:42:11 +0200 | [diff] [blame] | 116 | .. _writing-extensions: |
| 117 | |
| 118 | Writing Extensions |
| 119 | ------------------ |
| 120 | |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 121 | .. module:: jinja2.ext |
| 122 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 123 | By writing extensions you can add custom tags to Jinja2. This is a non trival |
| 124 | task and usually not needed as the default tags and expressions cover all |
| 125 | common use cases. The i18n extension is a good example of why extensions are |
| 126 | useful, another one would be fragment caching. |
| 127 | |
Armin Ronacher | b9e7875 | 2008-05-10 23:36:28 +0200 | [diff] [blame] | 128 | When writing extensions you have to keep in mind that you are working with the |
| 129 | Jinja2 template compiler which does not validate the node tree you are possing |
| 130 | to it. If the AST is malformed you will get all kinds of compiler or runtime |
| 131 | errors that are horrible to debug. Always make sure you are using the nodes |
| 132 | you create correctly. The API documentation below shows which nodes exist and |
| 133 | how to use them. |
| 134 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 135 | Example Extension |
| 136 | ~~~~~~~~~~~~~~~~~ |
| 137 | |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 138 | The following example implements a `cache` tag for Jinja2 by using the |
| 139 | `Werkzeug`_ caching contrib module: |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 140 | |
| 141 | .. literalinclude:: cache_extension.py |
| 142 | :language: python |
| 143 | |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 144 | And here is how you use it in an environment:: |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 145 | |
| 146 | from jinja2 import Environment |
| 147 | from werkzeug.contrib.cache import SimpleCache |
| 148 | |
Armin Ronacher | 762079c | 2008-05-08 23:57:56 +0200 | [diff] [blame] | 149 | env = Environment(extensions=[FragmentCacheExtension]) |
| 150 | env.fragment_cache = SimpleCache() |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 151 | |
Armin Ronacher | 6df604e | 2008-05-23 22:18:38 +0200 | [diff] [blame] | 152 | Inside the template it's then possible to mark blocks as cacheable. The |
| 153 | following example caches a sidebar for 300 seconds: |
| 154 | |
| 155 | .. sourcecode:: html+jinja |
| 156 | |
| 157 | {% cache 'sidebar', 300 %} |
| 158 | <div class="sidebar"> |
| 159 | ... |
| 160 | </div> |
| 161 | {% endcache %} |
| 162 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 163 | .. _Werkzeug: http://werkzeug.pocoo.org/ |
| 164 | |
| 165 | Extension API |
| 166 | ~~~~~~~~~~~~~ |
| 167 | |
| 168 | Extensions always have to extend the :class:`jinja2.ext.Extension` class: |
| 169 | |
| 170 | .. autoclass:: Extension |
Armin Ronacher | 9ad96e7 | 2008-06-13 22:44:01 +0200 | [diff] [blame] | 171 | :members: preprocess, filter_stream, parse, attr, call_method |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 172 | |
| 173 | .. attribute:: identifier |
| 174 | |
| 175 | The identifier of the extension. This is always the true import name |
| 176 | of the extension class and must not be changed. |
| 177 | |
| 178 | .. attribute:: tags |
| 179 | |
| 180 | If the extension implements custom tags this is a set of tag names |
| 181 | the extension is listening for. |
| 182 | |
| 183 | Parser API |
| 184 | ~~~~~~~~~~ |
| 185 | |
| 186 | The parser passed to :meth:`Extension.parse` provides ways to parse |
| 187 | expressions of different types. The following methods may be used by |
| 188 | extensions: |
| 189 | |
| 190 | .. autoclass:: jinja2.parser.Parser |
Armin Ronacher | 09c002e | 2008-05-10 22:21:30 +0200 | [diff] [blame] | 191 | :members: parse_expression, parse_tuple, parse_assign_target, |
Armin Ronacher | 7f15ef8 | 2008-05-16 09:11:39 +0200 | [diff] [blame] | 192 | parse_statements, free_identifier, fail |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 193 | |
| 194 | .. attribute:: filename |
| 195 | |
| 196 | The filename of the template the parser processes. This is **not** |
Armin Ronacher | 67fdddf | 2008-05-16 09:27:51 +0200 | [diff] [blame] | 197 | the load name of the template. For the load name see :attr:`name`. |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 198 | For templates that were not loaded form the file system this is |
| 199 | `None`. |
| 200 | |
Armin Ronacher | 67fdddf | 2008-05-16 09:27:51 +0200 | [diff] [blame] | 201 | .. attribute:: name |
| 202 | |
| 203 | The load name of the template. |
| 204 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 205 | .. attribute:: stream |
| 206 | |
| 207 | The current :class:`~jinja2.lexer.TokenStream` |
| 208 | |
| 209 | .. autoclass:: jinja2.lexer.TokenStream |
Armin Ronacher | fdf9530 | 2008-05-11 22:20:51 +0200 | [diff] [blame] | 210 | :members: push, look, eos, skip, next, next_if, skip_if, expect |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 211 | |
| 212 | .. attribute:: current |
| 213 | |
| 214 | The current :class:`~jinja2.lexer.Token`. |
| 215 | |
| 216 | .. autoclass:: jinja2.lexer.Token |
| 217 | :members: test, test_any |
| 218 | |
| 219 | .. attribute:: lineno |
| 220 | |
| 221 | The line number of the token |
| 222 | |
| 223 | .. attribute:: type |
| 224 | |
| 225 | The type of the token. This string is interned so you may compare |
| 226 | it with arbitrary strings using the `is` operator. |
| 227 | |
| 228 | .. attribute:: value |
| 229 | |
| 230 | The value of the token. |
| 231 | |
Armin Ronacher | d02fc7d | 2008-06-14 14:19:47 +0200 | [diff] [blame] | 232 | There is also a utility function in the lexer module that can count newline |
| 233 | characters in strings: |
| 234 | |
| 235 | .. autofunction:: jinja2.lexer.count_newlines |
| 236 | |
Armin Ronacher | 023b5e9 | 2008-05-08 11:03:10 +0200 | [diff] [blame] | 237 | AST |
| 238 | ~~~ |
| 239 | |
| 240 | The AST (Abstract Syntax Tree) is used to represent a template after parsing. |
| 241 | It's build of nodes that the compiler then converts into executable Python |
| 242 | code objects. Extensions that provide custom statements can return nodes to |
| 243 | execute custom Python code. |
| 244 | |
| 245 | The list below describes all nodes that are currently available. The AST may |
| 246 | change between Jinja2 versions but will stay backwards compatible. |
| 247 | |
| 248 | For more information have a look at the repr of :meth:`jinja2.Environment.parse`. |
| 249 | |
| 250 | .. module:: jinja2.nodes |
| 251 | |
| 252 | .. jinjanodes:: |
| 253 | |
| 254 | .. autoexception:: Impossible |