From 4c9cfccf24a1bc954cd9ddc25f5637efaaf43110 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 29 Apr 2007 18:21:13 +0200 Subject: [PATCH] [svn] splitted jinja documentation into more files --HG-- branch : trunk --- docs/src/builtins.txt | 203 ++++++++++++ docs/src/designerdoc.txt | 652 +------------------------------------- docs/src/escaping.txt | 71 +++++ docs/src/index.txt | 18 +- docs/src/inheritance.txt | 157 +++++++++ docs/src/objects.txt | 5 +- docs/src/scopes.txt | 161 ++++++++++ docs/src/templatei18n.txt | 72 +++++ 8 files changed, 690 insertions(+), 649 deletions(-) create mode 100644 docs/src/builtins.txt create mode 100644 docs/src/escaping.txt create mode 100644 docs/src/inheritance.txt create mode 100644 docs/src/scopes.txt create mode 100644 docs/src/templatei18n.txt diff --git a/docs/src/builtins.txt b/docs/src/builtins.txt new file mode 100644 index 0000000..7f460a4 --- /dev/null +++ b/docs/src/builtins.txt @@ -0,0 +1,203 @@ +=================================== +Filters, Tests and Helper Functions +=================================== + +This part of the documentation lists the filter-, test- and helper functions +you can use in templates. + + +Filters +======= + +In the examples above you might have noticed the pipe symbols. Pipe symbols tell +the engine that it has to apply a filter on the variable. Here is a small example: + +.. sourcecode:: jinja + + {{ variable|replace('foo', 'bar')|escape }} + +If you want, you can also put whitespace between the filters. + +This will look for a variable `variable`, pass it to the filter `replace` +with the arguments ``'foo'`` and ``'bar'``, and pass the result to the filter +`escape` that automatically XML-escapes the value. The `e` filter is an alias for +`escape`. Here is the complete list of supported filters: + +[[list_of_filters]] + +.. admonition:: note + + The filter operator has a pretty low priority. If you want to add fitered + values you have to put them into parentheses. The same applies if you want + to access attributes or return values: + + .. sourcecode:: jinja + + correct: + {{ (foo|filter) + (bar|filter) }} + wrong: + {{ foo|filter + bar|filter }} + + correct: + {{ (foo|filter).attribute }} + wrong: + {{ foo|filter.attribute }} + +*new in Jinja 1.1*: + +Because the application can provide additional filters you can get a documentation +of all the provided filters by calling ``debug.filters()``: + +.. sourcecode:: jinja + + {{ debug.filters() }} + -> returns a plain text representation of all the filters + + {{ debug.filters(False) }} + -> same as above but without the builtin ones. + +Tests +===== + +You can use the `is` operator to perform tests on a value: + +.. sourcecode:: jinja + + {{ 42 is numeric }} -> true + {{ "foobar" is numeric }} -> false + {{ 'FOO' is upper }} -> true + +These tests are especially useful when used in `if` conditions. + +[[list_of_tests]] + +*new in Jinja 1.1*: + +Because the application can provide additional tests you can get a documentation +of all the provided tests by calling ``debug.tests()``: + +.. sourcecode:: jinja + + {{ debug.tests() }} + -> returns a plain text representation of all the tests + + {{ debug.tests(False) }} + -> same as above but without the builtin ones. + + +Global Functions +================ + +Test functions and filter functions live in their own namespace. Global +functions not. They behave like normal objects in the context. Beside the +functions added by the application or framewhere there are two functions +available per default: + +`range` + + Works like the python `range function`_ just that it doesn't support + ranges greater than ``1000000``. + +`debug` + + Function that outputs the contents of the context. + +`lipsum` + + Generate some paragraphs of random text: + + .. sourcecode:: jinja + + {{ lipsum(5) }} + five html paragraphs + + {{ lipsum(2, False) }} + two ascii only paragraphs + + Per default a paragraph is between 20 and 100 words long. You can + override this default with the third and fourth parameter: + + .. sourcecode:: jinja + + {{ lipsum(10, True, 50, 200) }} + generate 10 HTML paragraphs between 50 and 200 words. + + *new in Jinja 1.1* + +`watchchanges` + + Jinja does not provide an django like ``{% ifchanged %}`` tag. As + replacement for this tag there is a special function in the namespace + called `watchchanges`. + + You can use it like this: + + .. sourcecode:: html+jinja + + {% for changed, article in watchchanges(articles, 'date', 'day') %} + {% if changed %}

{{ articles.date.day }}

{% endif %} +

{{ article.title|e }}

+

{{ article.body|e }}

+ {% endif %} + + For each iteration `watchchanges` will check the given attribute. If it + changed to the former iteration the first yielded item (in this example + it's called `changed`) will be `true`, else `false`. + + In this example `articles` is a list of articles for the template with + an attribute called `date.day` which represents the current day. To only + add a new day headline if the day has changed `watchchanges` is now told + to check `articles.date.days`. + + If you want to observe more than one attribute you can provide pairs: + + .. sourcecode:: html+jinja + + {% for changed, item in watchchanges(foo, ('a', 'b'), ('a', 'c')) %} + ... + {% endfor %} + + Note that if you want to watch two first level attributes you have to + either use the list syntax `[]` or add a colon: + + .. sourcecode:: html+jinja + + {% for changed, item in watchchanges(foo, ['a'], ('b',)) %} + ... + {% endfor %} + + otherwise Jinja cannot differ between a pair of parentheses to group + expressions or the sequence syntax. + + If you don't provide any arguments the value of the variable itself + is checked. + + *new in Jinja 1.1* + + +Global Constants +================ + +Jinja provides some special variables which cannot be overridden in templates. +Those are not affected by the variable lookup: + + `_`, `true`, `false`, `none`, `undefined` + +You cannot use those names for your own variables or macros. It's however no +problem to have blocks with that name. + +**Notice** due to a bug in Jinja 1.0 it was possible to override `_`, `true`, +`false`, `none` and `undefined` from the template by either using `{% set %}` +or in a for loop. While overriding `true`, `false` etc just caused nothing +overriding the translation marker `_` would crash the translation interface. +If you want to use `_` for unpacking in for loops (eg. skipping items) you +have to give it a proper name: + +.. sourcecode:: jinja + + {% for key, ignore in mydict|dictsort %} + {{ key|e }} + {% endfor %} + + +.. _range function: http://docs.python.org/tut/node6.html#SECTION006300000000000000000 diff --git a/docs/src/designerdoc.txt b/docs/src/designerdoc.txt index 6c6dbab..ba5de71 100644 --- a/docs/src/designerdoc.txt +++ b/docs/src/designerdoc.txt @@ -67,174 +67,6 @@ this: If you have numerical indices you have to use the [] syntax: {{ users[0].username }} -Filters -======= - -In the examples above you might have noticed the pipe symbols. Pipe symbols tell -the engine that it has to apply a filter on the variable. Here is a small example: - -.. sourcecode:: jinja - - {{ variable|replace('foo', 'bar')|escape }} - -If you want, you can also put whitespace between the filters. - -This will look for a variable `variable`, pass it to the filter `replace` -with the arguments ``'foo'`` and ``'bar'``, and pass the result to the filter -`escape` that automatically XML-escapes the value. The `e` filter is an alias for -`escape`. Here is the complete list of supported filters: - -[[list_of_filters]] - -.. admonition:: note - - The filter operator has a pretty low priority. If you want to add fitered - values you have to put them into parentheses. The same applies if you want - to access attributes or return values: - - .. sourcecode:: jinja - - correct: - {{ (foo|filter) + (bar|filter) }} - wrong: - {{ foo|filter + bar|filter }} - - correct: - {{ (foo|filter).attribute }} - wrong: - {{ foo|filter.attribute }} - -*new in Jinja 1.1*: - -Because the application can provide additional filters you can get a documentation -of all the provided filters by calling ``debug.filters()``: - -.. sourcecode:: jinja - - {{ debug.filters() }} - -> returns a plain text representation of all the filters - - {{ debug.filters(False) }} - -> same as above but without the builtin ones. - -Tests -===== - -You can use the `is` operator to perform tests on a value: - -.. sourcecode:: jinja - - {{ 42 is numeric }} -> true - {{ "foobar" is numeric }} -> false - {{ 'FOO' is upper }} -> true - -These tests are especially useful when used in `if` conditions. - -[[list_of_tests]] - -*new in Jinja 1.1*: - -Because the application can provide additional tests you can get a documentation -of all the provided tests by calling ``debug.tests()``: - -.. sourcecode:: jinja - - {{ debug.tests() }} - -> returns a plain text representation of all the tests - - {{ debug.tests(False) }} - -> same as above but without the builtin ones. - - -Global Functions -================ - -Test functions and filter functions live in their own namespace. Global -functions not. They behave like normal objects in the context. Beside the -functions added by the application or framewhere there are two functions -available per default: - -`range` - - Works like the python `range function`_ just that it doesn't support - ranges greater than ``1000000``. - -`debug` - - Function that outputs the contents of the context. - -`lipsum` - - Generate some paragraphs of random text: - - .. sourcecode:: jinja - - {{ lipsum(5) }} - five html paragraphs - - {{ lipsum(2, False) }} - two ascii only paragraphs - - Per default a paragraph is between 20 and 100 words long. You can - override this default with the third and fourth parameter: - - .. sourcecode:: jinja - - {{ lipsum(10, True, 50, 200) }} - generate 10 HTML paragraphs between 50 and 200 words. - - *new in Jinja 1.1* - -`watchchanges` - - Jinja does not provide an django like ``{% ifchanged %}`` tag. As - replacement for this tag there is a special function in the namespace - called `watchchanges`. - - You can use it like this: - - .. sourcecode:: html+jinja - - {% for changed, article in watchchanges(articles, 'date', 'day') %} - {% if changed %}

{{ articles.date.day }}

{% endif %} -

{{ article.title|e }}

-

{{ article.body|e }}

- {% endif %} - - For each iteration `watchchanges` will check the given attribute. If it - changed to the former iteration the first yielded item (in this example - it's called `changed`) will be `true`, else `false`. - - In this example `articles` is a list of articles for the template with - an attribute called `date.day` which represents the current day. To only - add a new day headline if the day has changed `watchchanges` is now told - to check `articles.date.days`. - - If you want to observe more than one attribute you can provide pairs: - - .. sourcecode:: html+jinja - - {% for changed, item in watchchanges(foo, ('a', 'b'), ('a', 'c')) %} - ... - {% endfor %} - - Note that if you want to watch two first level attributes you have to - either use the list syntax `[]` or add a colon: - - .. sourcecode:: html+jinja - - {% for changed, item in watchchanges(foo, ['a'], ('b',)) %} - ... - {% endfor %} - - otherwise Jinja cannot differ between a pair of parentheses to group - expressions or the sequence syntax. - - If you don't provide any arguments the value of the variable itself - is checked. - - *new in Jinja 1.1* - Loops ===== @@ -252,7 +84,7 @@ normal Python `for` loop and works pretty much the same: {% endfor %} -*Important* Contrary to Python is the optional ``else`` block only +*Important* Contrary to Python is the optional `else` block only executed if there was no iteration because the sequence was empty. Inside of a `for` loop block you can access some special variables: @@ -516,164 +348,8 @@ You can also specify more than one value: If a macro parameter is called `varargs` the additional extra arguments are not accessible. - -Inheritance -=========== - -The most powerful part of Jinja is template inheritance. Template inheritance -allows you to build a base "skeleton" template that contains all the common -elements of your site and defines **blocks** that child templates can override. - -Sounds complicated but is very basic. It's easiest to understand it by starting -with an example. - -Base Template -------------- - -This template, which we'll call ``base.html``, defines a simple HTML skeleton -document that you might use for a simple two-column page. It's the job of -"child" templates to fill the empty blocks with content: - -.. sourcecode:: html+jinja - - - - - - {% block title %}{% endblock %} - My Webpage - {% block html_head %}{% endblock %} - - -
- {% block content %}{% endblock %} -
- - - - -In this example, the ``{% block %}`` tags define four blocks that child templates -can fill in. All the `block` tag does is to tell the template engine that a -child template may override those portions of the template. - -Child Template --------------- - -A child template might look like this: - -.. sourcecode:: html+jinja - - {% extends "base.html" %} - {% block title %}Index{% endblock %} - - {% block html_head %} - - {% endblock %} - - {% block content %} -

Index

-

- Welcome on my awsome homepage. -

- {% endblock %} - -The ``{% extends %}`` tag is the key here. It tells the template engine that -this template "extends" another template. When the template system evaluates -this template, first it locates the parent. - -The filename of the template depends on the template loader. For example the -``FileSystemLoader`` allows you to access other templates by giving the -filename. You can access templates in subdirectories with an slash: - -.. sourcecode:: jinja - - {% extends "layout/default.html" %} - -But this behavior can depend on the application using Jinja. - -Note that since the child template didn't define the ``footer`` block, the -value from the parent template is used instead. - -.. admonition:: Note - - You can't define multiple ``{% block %}`` tags with the same name in the - same template. This limitation exists because a block tag works in "both" - directions. That is, a block tag doesn't just provide a hole to fill - it - also defines the content that fills the hole in the *parent*. If there were - two similarly-named ``{% block %}`` tags in a template, that template's - parent wouldn't know which one of the blocks' content to use. - -How Inheritance Works Internally --------------------------------- - -Inheritance in Jinja is straighforward. If a template contains a -``{% extends %}`` tag it's considered being a child template, otherwise it's -a layout template. In a layout template you can place blocks basically -everywhere. In a child template blocks can only be located either top level -or inside of another block. - -Data outside of a block in a child template is executed before the layout -template is rendered, thus you can use it to propagate data to the whole -inheritance chain. Having a block in an invalid position you will receive -an syntax error. Here some examples: - -**impossible**: - - .. sourcecode:: jinja - - {% extends 'master.html' %} - {% if some_condition %} - {% block body %} - ... - {% endblock %} - {% endif %} - - This can't work because template inheritance works at translation / - compilation time not at template executation. - -**possible**: - - .. sourcecode:: jinja - - {% extends 'master.html' %} - {% block body %} - {% if some_condition %} - {% block myblock %} - ... - {% endblock %} - {% endblock %} - {% endblock %} - - This can work although it probably makes no sense in this specific case. - However the condition is handled at runtime because it's in a valid block - and defines a new block subtemplates can override. - -Super Blocks -============ - -Starting with `Jinja 1.1` it's possible to render the contents of the parent -block. By calling it you get the results of the parent block back. If you want -to get the data of the parent you can give it an offset: - -.. sourcecode:: jinja - - {{ super() }} - return the parent data - - {{ super(1) }} - the same as above - - {{ super(2) }} - return the data of the second parent block - +For information regarding the visibility of macros have a look at the +`Scopes and Variable Behavior`_ section. Template Inclusion ================== @@ -690,6 +366,8 @@ load macros, `include` works better than `extends`: If you define a macro called ``my_helper`` in ``myhelpers.html``, you can now use it from the template as shown above. +Because of the + Filtering Blocks ================ @@ -726,187 +404,8 @@ You can also define variables in the namespace using the ``{% set %}`` tag: This should ouput ``foobar``. -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|default('Untitled') }} - {% 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|default('Untitled') }} - - {{ wrap(42) }} - - -.. 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. - - -Escaping -======== - -Sometimes you might want to add Jinja syntax elements into the template -without executing them. In that case you have quite a few possibilities. - -For small parts this might be a good way: - -.. sourcecode:: jinja - - {{ "{{ foo }} is variable syntax and {% foo %} is block syntax" }} - -When you have multiple elements you can use the ``raw`` block: - -.. sourcecode:: jinja - - {% raw %} - Filtering blocks works like this in Jinja: - {% filter escape %} - - goes here - - {% endfilter %} - {% endraw %} +For information regarding the visibility of variables have a look at the +`Scopes and Variable Behavior`_ section. Reserved Keywords ================= @@ -936,141 +435,6 @@ means that they won't raise an error for several releases but yield warnings on the application side. But it's very unlikely that new keywords will be added. -Global Constants -================ - -Jinja provides some special variables which cannot be overridden in templates. -Those are not affected by the variable lookup: - - `_`, `true`, `false`, `none`, `undefined` - -You cannot use those names for your own variables or macros. It's however no -problem to have blocks with that name. - -**Notice** due to a bug in Jinja 1.0 it was possible to override `_`, `true`, -`false`, `none` and `undefined` from the template by either using `{% set %}` -or in a for loop. While overriding `true`, `false` etc just caused nothing -overriding the translation marker `_` would crash the translation interface. -If you want to use `_` for unpacking in for loops (eg. skipping items) you -have to give it a proper name: - -.. sourcecode:: jinja - - {% for key, ignore in mydict|dictsort %} - {{ key|e }} - {% endfor %} - -Whitespace -========== - -If the Jinja environment was created with ``trim_blocks`` set to true the -first newline after a template tag is removed automatically (php like -processing). - -Starting with `Jinja 1.1` you can also handle some whitespace rules in the -template. If you put an minus sign (`-`) to the start or end of an block -(for example a `for` tag) or a comment, variable element you can remove -the whitespaces after that block or before that block: - -.. sourcecode:: jinja - - {% for item in seq -%} - {{ item }} - {%- endfor %} - -This will yield all elements without whitespace between them because they -are automatically removed. This of course works for other tags too: - -.. sourcecode:: jinja - - {% for user in userlist -%} - {{ user|e -}} - {% if not loop.last %},{% endif %} - {%- endfor %} - -Note that you must not use a whitespace between the tag and the minus sign: - -.. sourcecode:: jinja - - valid: - {%- if foo -%}...{% endif %} - - invalid: - - {% - if foo - %}...{% endif %} - -Internationalization -==================== - -If the application is configured for i18n, you can define translatable blocks -for translators using the `trans` tag or the special underscore function: - -.. sourcecode:: jinja - - {% trans %} - this is a translatable block - {% endtrans %} - - {% trans "This is a translatable string" %} - - {{ _("This is a translatable string") }} - -The latter one is useful if you want translatable arguments for filters etc. - -If you want to have plural forms too, use the `pluralize` block: - -.. sourcecode:: jinja - - {% trans users=users %} - One user found. - {% pluralize %} - {{ users }} users found. - {% endtrans %} - - {% trans first=(users|first).username|escape, user=users|length %} - one user {{ first }} found. - {% pluralize users %} - {{ users }} users found, the first one is called {{ first }}. - {% endtrans %} - -If you have multiple arguments, the first one is assumed to be the indicator (the -number that is used to determine the correct singular or plural form. If you -don't have the indicator variable on position 1 you have to tell the `pluralize` -tag the correct variable name. - -Inside translatable blocks you cannot use blocks or expressions (however you can -still use the ``raw`` block which will work as expected). The variable -print syntax (``{{ variablename }}``) is the only way to insert the variables -defined in the ``trans`` header. Filters must be applied in the header. - -.. admonition:: note - - Please make sure that you always use pluralize blocks where required. - Many languages have more complex plural forms than the English language. - - Never try to workaround that issue by using something like this: - - .. sourcecode:: jinja - - {% if count != 1 %} - {{ count }} users found. - {% else %} - one user found. - {% endif %} - -*New in Jinja 1.1*: It's now possible to use the marker name as implicit -default: - -.. sourcecode:: jinja - - instead of this version: - - {% trans username=username %}Hello {{ username }}!{% endtrans %} - - you can now write this: - - {% trans username %}Hello {{ username }}!{% endtrans %} - Bleeding Edge ============= @@ -1133,4 +497,4 @@ change. .. _slicing chapter: http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice -.. _range function: http://docs.python.org/tut/node6.html#SECTION006300000000000000000 +.. _Scopes and Variable Behavior: scopes.txt diff --git a/docs/src/escaping.txt b/docs/src/escaping.txt new file mode 100644 index 0000000..ab7e8d6 --- /dev/null +++ b/docs/src/escaping.txt @@ -0,0 +1,71 @@ +======================= +Whitespace and Escaping +======================= + +This section of the documentation explains how to remove unused whitespace +from the templates and embed raw Jinja syntax. + +Escaping +======== + +Sometimes you might want to add Jinja syntax elements into the template +without executing them. In that case you have quite a few possibilities. + +For small parts this might be a good way: + +.. sourcecode:: jinja + + {{ "{{ foo }} is variable syntax and {% foo %} is block syntax" }} + +When you have multiple elements you can use the ``raw`` block: + +.. sourcecode:: jinja + + {% raw %} + Filtering blocks works like this in Jinja: + {% filter escape %} + + goes here + + {% endfilter %} + {% endraw %} + + +Whitespace +========== + +If the Jinja environment was created with ``trim_blocks`` set to true the +first newline after a template tag is removed automatically (php like +processing). + +Starting with `Jinja 1.1` you can also handle some whitespace rules in the +template. If you put an minus sign (`-`) to the start or end of an block +(for example a `for` tag) or a comment, variable element you can remove +the whitespaces after that block or before that block: + +.. sourcecode:: jinja + + {% for item in seq -%} + {{ item }} + {%- endfor %} + +This will yield all elements without whitespace between them because they +are automatically removed. This of course works for other tags too: + +.. sourcecode:: jinja + + {% for user in userlist -%} + {{ user|e -}} + {% if not loop.last %},{% endif %} + {%- endfor %} + +Note that you must not use a whitespace between the tag and the minus sign: + +.. sourcecode:: jinja + + valid: + {%- if foo -%}...{% endif %} + + invalid: + + {% - if foo - %}...{% endif %} diff --git a/docs/src/index.txt b/docs/src/index.txt index d591fd1..ba1c4eb 100644 --- a/docs/src/index.txt +++ b/docs/src/index.txt @@ -47,8 +47,22 @@ Welcome in the Jinja documentation. - **Template Designer Documentation**: - - `Syntax Reference `_ - the designer documentation. Put - this under your pillow. + - `Syntax Reference `_ - quick overview over the Jinja + syntax elements. + + - `Template Inheritance `_ - template inheritance howto. + + - `Filters, Tests and Helper Functions `_ - list of filters + and test/helper functions. + + - `Whitespace and Escaping `_ - how to escape markup and + control whitespace. + + - `Scopes and Variable Behavior `_ - behavior of undefined + variables and scoping rules. + + - `Template Internationalization `_ - how to internationalize + Jinja templates. - `Differences To Django `_ - coming from django? Then this document is for you. diff --git a/docs/src/inheritance.txt b/docs/src/inheritance.txt new file mode 100644 index 0000000..94bae87 --- /dev/null +++ b/docs/src/inheritance.txt @@ -0,0 +1,157 @@ +==================== +Template Inheritance +==================== + +The most powerful part of Jinja is template inheritance. Template inheritance +allows you to build a base "skeleton" template that contains all the common +elements of your site and defines **blocks** that child templates can override. + +Sounds complicated but is very basic. It's easiest to understand it by starting +with an example. + +Base Template +============= + +This template, which we'll call ``base.html``, defines a simple HTML skeleton +document that you might use for a simple two-column page. It's the job of +"child" templates to fill the empty blocks with content: + +.. sourcecode:: html+jinja + + + + + + {% block title %}{% endblock %} - My Webpage + {% block html_head %}{% endblock %} + + +
+ {% block content %}{% endblock %} +
+ + + + +In this example, the ``{% block %}`` tags define four blocks that child templates +can fill in. All the `block` tag does is to tell the template engine that a +child template may override those portions of the template. + +Child Template +============== + +A child template might look like this: + +.. sourcecode:: html+jinja + + {% extends "base.html" %} + {% block title %}Index{% endblock %} + + {% block html_head %} + + {% endblock %} + + {% block content %} +

Index

+

+ Welcome on my awsome homepage. +

+ {% endblock %} + +The ``{% extends %}`` tag is the key here. It tells the template engine that +this template "extends" another template. When the template system evaluates +this template, first it locates the parent. + +The filename of the template depends on the template loader. For example the +``FileSystemLoader`` allows you to access other templates by giving the +filename. You can access templates in subdirectories with an slash: + +.. sourcecode:: jinja + + {% extends "layout/default.html" %} + +But this behavior can depend on the application using Jinja. + +Note that since the child template didn't define the ``footer`` block, the +value from the parent template is used instead. + +.. admonition:: Note + + You can't define multiple ``{% block %}`` tags with the same name in the + same template. This limitation exists because a block tag works in "both" + directions. That is, a block tag doesn't just provide a hole to fill - it + also defines the content that fills the hole in the *parent*. If there were + two similarly-named ``{% block %}`` tags in a template, that template's + parent wouldn't know which one of the blocks' content to use. + +How Inheritance Works Internally +================================ + +Inheritance in Jinja is straighforward. If a template contains a +``{% extends %}`` tag it's considered being a child template, otherwise it's +a layout template. In a layout template you can place blocks basically +everywhere. In a child template blocks can only be located either top level +or inside of another block. + +Data outside of a block in a child template is executed before the layout +template is rendered, thus you can use it to propagate data to the whole +inheritance chain. Having a block in an invalid position you will receive +an syntax error. Here some examples: + +**impossible**: + + .. sourcecode:: jinja + + {% extends 'master.html' %} + {% if some_condition %} + {% block body %} + ... + {% endblock %} + {% endif %} + + This can't work because template inheritance works at translation / + compilation time not at template executation. + +**possible**: + + .. sourcecode:: jinja + + {% extends 'master.html' %} + {% block body %} + {% if some_condition %} + {% block myblock %} + ... + {% endblock %} + {% endblock %} + {% endblock %} + + This can work although it probably makes no sense in this specific case. + However the condition is handled at runtime because it's in a valid block + and defines a new block subtemplates can override. + +Super Blocks +============ + +Starting with `Jinja 1.1` it's possible to render the contents of the parent +block. By calling it you get the results of the parent block back. If you want +to get the data of the parent you can give it an offset: + +.. sourcecode:: jinja + + {{ super() }} + return the parent data + + {{ super(1) }} + the same as above + + {{ super(2) }} + return the data of the second parent block diff --git a/docs/src/objects.txt b/docs/src/objects.txt index 6d9add9..b1f86e4 100644 --- a/docs/src/objects.txt +++ b/docs/src/objects.txt @@ -90,9 +90,8 @@ access. You can mark both attributes and methods as unsafe: # just give access to a and b. Default is all # note that this also disallows the functions from below. - # if you use jinja_allowed_attributes you don't have to - # do the code below because methods are threaded as attributes - # too. + # if you use jinja_allowed_attributes you don't have add the + # code below since methods are treated as attributes too. jinja_allowed_attributes = ['a', 'b'] def __init__(self, ...): diff --git a/docs/src/scopes.txt b/docs/src/scopes.txt new file mode 100644 index 0000000..205c8b4 --- /dev/null +++ b/docs/src/scopes.txt @@ -0,0 +1,161 @@ +============================ +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|default('Untitled') }} + {% 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|default('Untitled') }} + + {{ wrap(42) }} + + +.. 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. diff --git a/docs/src/templatei18n.txt b/docs/src/templatei18n.txt new file mode 100644 index 0000000..50ed017 --- /dev/null +++ b/docs/src/templatei18n.txt @@ -0,0 +1,72 @@ +============================= +Template Internationalization +============================= + +If the application is configured for i18n, you can define translatable blocks +for translators using the `trans` tag or the special underscore function: + +.. sourcecode:: jinja + + {% trans %} + this is a translatable block + {% endtrans %} + + {% trans "This is a translatable string" %} + + {{ _("This is a translatable string") }} + +The latter one is useful if you want translatable arguments for filters etc. + +If you want to have plural forms too, use the `pluralize` block: + +.. sourcecode:: jinja + + {% trans users=users %} + One user found. + {% pluralize %} + {{ users }} users found. + {% endtrans %} + + {% trans first=(users|first).username|escape, user=users|length %} + one user {{ first }} found. + {% pluralize users %} + {{ users }} users found, the first one is called {{ first }}. + {% endtrans %} + +If you have multiple arguments, the first one is assumed to be the indicator (the +number that is used to determine the correct singular or plural form. If you +don't have the indicator variable on position 1 you have to tell the `pluralize` +tag the correct variable name. + +Inside translatable blocks you cannot use blocks or expressions (however you can +still use the ``raw`` block which will work as expected). The variable +print syntax (``{{ variablename }}``) is the only way to insert the variables +defined in the ``trans`` header. Filters must be applied in the header. + +.. admonition:: note + + Please make sure that you always use pluralize blocks where required. + Many languages have more complex plural forms than the English language. + + Never try to workaround that issue by using something like this: + + .. sourcecode:: jinja + + {% if count != 1 %} + {{ count }} users found. + {% else %} + one user found. + {% endif %} + +*New in Jinja 1.1*: It's now possible to use the marker name as implicit +default: + +.. sourcecode:: jinja + + instead of this version: + + {% trans username=username %}Hello {{ username }}!{% endtrans %} + + you can now write this: + + {% trans username %}Hello {{ username }}!{% endtrans %} -- 2.26.2