Various cleanups and added custom cycler.
[jinja2.git] / docs / templates.rst
index 182ef9468b7b33e1c2e3375499c3060e3ef27b56..d797fec047e14ff30e398b3b0bc545ef450e69ee 100644 (file)
@@ -59,7 +59,7 @@ too.  How a variable looks like, heavily depends on the application providing
 those.
 
 You can use a dot (``.``) to access attributes of a variable, alternative the
-so-called "subscribe" syntax (``[]``) can be used.  The following lines do
+so-called "subscript" syntax (``[]``) can be used.  The following lines do
 the same::
 
     {{ foo.bar }}
@@ -74,6 +74,28 @@ value.  What you can do with that kind of value depends on the application
 configuration, the default behavior is that it evaluates to an empty string
 if printed and that you can iterate over it, but every other operation fails.
 
+.. _notes-on-subscriptions:
+
+.. admonition:: Implementation
+
+    For convenience sake ``foo.bar`` in Jinja2 does the following things on
+    the Python layer:
+
+    -   check if there is an attribute called `bar` on `foo`.
+    -   if there is not, check if there is an item ``'bar'`` in `foo`.
+    -   if there is not, return an undefined object.
+
+    ``foo['bar']`` on the other hand works mostly the same with the a small
+    difference in the order:
+
+    -   check if there is an item ``'bar'`` in `foo`.
+    -   if there is not, check if there is an attribute called `bar` on `foo`.
+    -   if there is not, return an undefined object.
+
+    This is important if an object has an item or attribute with the same
+    name.  Additionally there is the :func:`attr` filter that just looks up
+    attributes.
+
 .. _filters:
 
 Filters
@@ -218,6 +240,19 @@ precedes it.  For better readability statements that start a block (such as
     # endfor
 
 
+.. admonition:: Note
+
+    Line statements can span multiple lines if there are open parentheses,
+    braces or brackets::
+
+        <ul>
+        # for href, caption in [('index.html', 'Index'),
+                                ('about.html', 'About')]:
+            <li><a href="{{ href }}">{{ caption }}</a></li>
+        # endfor
+        </ul>
+
+
 .. _template-inheritance:
 
 Template Inheritance
@@ -311,7 +346,6 @@ If you want to print a block multiple times you can however use the special
     <h1>{{ self.title() }}</h1>
     {% block body %}{% endblock %}
 
-
 Unlike Python Jinja does not support multiple inheritance.  So you can only have
 one extends tag called per rendering.
 
@@ -448,6 +482,9 @@ each time through the loop by using the special `loop.cycle` helper::
         <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
     {% endfor %}
 
+With Jinja 2.1 an extra `cycle` helper exists that allows loop-unbound
+cycling.  For more information have a look at the :ref:`builtin-globals`.
+
 .. _loop-filtering:
 
 Unlike in Python it's not possible to `break` or `continue` in a loop.  You
@@ -580,6 +617,9 @@ are available on a macro object:
     This is `true` if the macro accesses the special `caller` variable and may
     be called from a :ref:`call<call>` tag.
 
+If a macro name starts with an underscore it's not exported and can't
+be imported.
+
 
 .. _call:
 
@@ -629,6 +669,17 @@ Here an example of how a call block can be used with arguments::
     {% endcall %}
 
 
+Filters
+~~~~~~~
+
+Filter sections allow you to apply regular Jinja2 filters on a block of
+template data.  Just wrap the code in the special `filter` section::
+
+    {% filter upper %}
+        This text becomes uppercase
+    {% endfilter %}
+
+
 Assignments
 ~~~~~~~~~~~
 
@@ -746,6 +797,19 @@ Here two examples::
     {% from 'forms.html' import input with context %}
     {% include 'header.html' without context %}
 
+.. admonition:: Note
+
+    In Jinja 2.0 the context that was passed to the included template
+    did not include variables define in the template.  As a matter of
+    fact this did not work::
+
+        {% for box in boxes %}
+            {% include "render_box.html" %}
+        {% endfor %}
+
+    The included template ``render_box.html`` is not able to access
+    `box` in Jinja 2.0, but in Jinja 2.1.
+
 
 .. _expressions:
 
@@ -917,6 +981,11 @@ variable is defined, otherwise from the default layout template::
 The general syntax is ``<do something> if <something is true> else <do
 something else>``.
 
+The `else` part is optional.  If not provided the else block implicitly
+evaluates into an undefined object::
+
+    {{ '[%s]' % page.title if page.title }}
+
 
 .. _builtin-filters:
 
@@ -933,6 +1002,7 @@ List of Builtin Tests
 
 .. jinjatests::
 
+.. _builtin-globals:
 
 List of Global Functions
 ------------------------
@@ -972,6 +1042,44 @@ The following functions are available in the global scope by default:
     A convenient alternative to dict literals.  ``{'foo': 'bar'}`` is the same
     as ``dict(foo='bar')``.
 
+.. class:: cycler(\*items)
+
+    The cycler allows you to cycle among values similar to how `loop.cycle`
+    works.  Unlike `loop.cycle` however you can use this cycler outside of
+    loops or over multiple loops.
+
+    This is for example very useful if you want to show a list of folders and
+    files, with the folders on top, but both in the same list with alteranting
+    row colors.
+
+    The following example shows how `cycler` can be used::
+
+        {% set row_class = cycler('odd', 'even') %}
+        <ul class="browser">
+        {% for folder in folders %}
+          <li class="folder {{ row_class.next() }}">{{ folder|e }}</li>
+        {% endfor %}
+        {% for filename in files %}
+          <li class="file {{ row_class.next() }}">{{ filename|e }}</li>
+        {% endfor %}
+        </ul>
+
+    A cycler has the following attributes and methods:
+
+    .. method:: reset()
+
+        Resets the cycle to the first item.
+
+    .. method:: next()
+
+        Goes one item a head and returns the then current item.
+
+    .. attribute:: current
+
+        Returns the current item.
+    
+    **new in Jinja 2.1**
+
 
 Extensions
 ----------