| ============================ |
| Scopes and Variable Behavior |
| ============================ |
| |
| This section of the documentation covers the Jinja behavior regarding |
| variable visibility. |
| |
| |
| Scopes |
| ====== |
| |
| Jinja has multiple scopes. A scope is something like a new transparent foil on |
| a stack of foils. You can only write to the outermost foil but read all of them |
| since you can look through them. If you remove the top foil all data on that |
| foil disappears. Some tags in Jinja add a new layer to the stack. Currently |
| these are `block`, `for`, `macro` and `filter`. This means that variables and |
| other elements defined inside a macro, loop or some of the other tags listed |
| above will be only available in that block. Here an example: |
| |
| .. sourcecode:: jinja |
| |
| {% macro angryhello name %} |
| {% set angryname = name|upper %} |
| Hello {{ name }}. Hello {{ name }}! |
| HELLO {{ angryname }}!!!!!!111 |
| {% endmacro %} |
| |
| The variable ``angryname`` just exists inside the macro, not outside it. |
| |
| Defined macros appear on the context as variables. Because of this, they are |
| affected by the scoping too. A macro defined inside of a macro is just available |
| in those two macros (the macro itself and the macro it's defined in). |
| |
| |
| Template Globals |
| ================ |
| |
| A special threatment exists for template code outside of visible blocks in |
| child templates. This code will be executed **before** the layout template |
| code. Thus it can be used to propagate values back to the layout template or |
| import macros from templates for rendering. |
| |
| Such code can output data but it won't appear in the final rendering. So no |
| additional whitespace will pollute the template. |
| |
| Because this code is executed before the actual layout template code it's |
| possible that the layout code overrides some of those variables. Usually |
| this is not a problem because of different variable names but it can be |
| a problem if you plan to specify default values. |
| |
| In that case you have to test if the variable is not defined before setting |
| it: |
| |
| .. sourcecode:: jinja |
| |
| {% if not page_title %} |
| {% set page_title = 'Default Page Title' %} |
| {% endif %} |
| |
| You can of course also use the `|default` filter. |
| |
| .. admonition:: Explanation |
| |
| This template stored as `a.html`: |
| |
| .. sourcecode:: html+jinja |
| |
| <title>{{ title|default('Untitled') }}</title> |
| <body>{% block body %}{% endblock %} |
| |
| ...and this child template stored as `b.html`: |
| |
| .. sourcecode:: html+jinja |
| |
| {% extends 'a.html' %} |
| {% include 'macros.tmpl' %} |
| {% set title = 'My Page' %} |
| {% block body %}{{ wrap(42) }}{% endblock %} |
| |
| ...and this code in `macros.tmpl`: |
| |
| .. sourcecode:: html+jinja |
| |
| {% macro wrap(text) %} |
| [{{ text }}] |
| {% endmacro %} |
| |
| ..will translate to something with the same semantics as this (just |
| that the value is not stored in a variable): |
| |
| .. sourcecode:: html+jinja |
| |
| {% filter capture('captured', true) %} |
| {% macro wrap(text) %} |
| [{{ text }}] |
| {% endmacro %} |
| {% set title='My Page' %} |
| {% endfilter %} |
| <title>{{ title|default('Untitled') }}</title> |
| <body> |
| {{ wrap(42) }} |
| </body> |
| |
| .. admonition:: Note |
| |
| This implementation was improved in Jinja 1.1. In Jinja 1.0 blocks that |
| were not top-level were not propagated to the layout template. This made |
| it impossible to use conditional expressions for inclusion in non root |
| templates. |
| |
| |
| Undefined Variables |
| =================== |
| |
| If you have already worked with python you probably know about the fact that |
| undefined variables raise an exception. This is different in Jinja. There is a |
| special value called `undefined` that represents values that do not exist. |
| |
| Depending on the configuration it will behave different. |
| |
| In order to check if a value is defined you can use the `defined` test: |
| |
| .. sourcecode:: jinja |
| |
| {{ myvariable is not defined }} |
| will return true if the variable does not exist. |
| |
| `SilentUndefined`: |
| |
| The silent `undefined` is the default behavior. The `undefined` object works |
| complete different from any variables you maybe know. If you print it |
| using ``{{ variable }}`` it will not appear because it's literally empty. |
| If you try to iterate over it, it will work. But no items are returned. |
| |
| In order to check if a value is defined you can use the `defined` test: |
| |
| There are also some additional rules regarding this special value. Any |
| mathematical operators (``+``, ``-``, ``*``, ``/``) return the operand |
| as result: |
| |
| .. sourcecode:: jinja |
| |
| {{ undefined + "foo" }} |
| returns "foo" |
| |
| {{ undefined - 42 }} |
| returns 42. Note: not -42! |
| |
| In any expression `undefined` evaluates to `false`. It has no length, all |
| attribute calls return undefined, calling too: |
| |
| .. sourcecode:: jinja |
| |
| {{ undefined.attribute().attribute_too[42] }} |
| still returns `undefined`. |
| |
| `ComplainingUndefined`: |
| |
| Starting with Jinja 1.1 it's possible to replace the default undefined |
| object with different values. The other common undefined object which |
| comes with Jinja is the `ComplainingUndefined` object. |
| |
| It raises exceptions as soon as you either render it or want to iterate |
| over it or try to access attributes etc. |
| |
| |
| Overriding Variables Of Outer Scopes |
| ==================================== |
| |
| *New in Jinja 1.2* |
| |
| Normally you cannot override a variable from an outer scope, you can just hide |
| it. There is however a way to override a variable from an outer scope using the |
| `set` tag, postfixed with a bang (!): |
| |
| .. sourcecode:: jinja |
| |
| {% set last_item = none %} |
| {% for item in seq %} |
| {% set last_item = item! %} |
| {% endfor %} |
| |
| After the iteration `last_item` will point to the item of the last iteration. |
| |
| If `last_item` was not defined in the outer scope it would be defined in the |
| outermost scope. |