diff options
| author | Luke Plant <L.Plant.98@cantab.net> | 2009-12-09 22:40:36 +0000 |
|---|---|---|
| committer | Luke Plant <L.Plant.98@cantab.net> | 2009-12-09 22:40:36 +0000 |
| commit | 2c2f5aee4d44836779fcd74c7782368914f9cfd1 (patch) | |
| tree | 686d60b434ffe9ebcc019ef61208e5cd45921ab9 /docs | |
| parent | 25020ddb05543fff1c37d77b49bd937fd2bbb170 (diff) | |
Implemented 'smart if' template tag, allowing filters and various operators to be used in the 'if' tag
Thanks to Chris Beaven for the initial patch, Fredrik Lundh for the basis
of the parser methodology and Russell Keith-Magee for code reviews.
There are some BACKWARDS INCOMPATIBILITIES in rare cases - in particular, if
you were using the keywords 'and', 'or' or 'not' as variable names within
the 'if' expression, which was previously allowed in some cases.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@11806 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ref/templates/builtins.txt | 160 | ||||
| -rw-r--r-- | docs/releases/1.2.txt | 43 | ||||
| -rw-r--r-- | docs/topics/templates.txt | 21 |
3 files changed, 200 insertions, 24 deletions
diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 6d6abd1098..bf2d9e899c 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -313,6 +313,9 @@ displayed by the ``{{ athlete_list|length }}`` variable. As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that will be displayed if the test fails. +Boolean operators +^^^^^^^^^^^^^^^^^ + ``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or to negate a given variable:: @@ -338,24 +341,153 @@ to negate a given variable:: There are some athletes and absolutely no coaches. {% endif %} -``if`` tags don't allow ``and`` and ``or`` clauses within the same tag, because -the order of logic would be ambiguous. For example, this is invalid:: +.. versionchanged:: 1.2 + +Use of both ``and`` and ``or`` clauses within the same tag is allowed, with +``and`` having higher precedence than ``or`` e.g.:: {% if athlete_list and coach_list or cheerleader_list %} -If you need to combine ``and`` and ``or`` to do advanced logic, just use nested -``if`` tags. For example:: +will be interpreted like: - {% if athlete_list %} - {% if coach_list or cheerleader_list %} - We have athletes, and either coaches or cheerleaders! - {% endif %} +.. code-block:: python + + if (athlete_list and coach_list) or cheerleader_list + +Use of actual brackets in the ``if`` tag is invalid syntax. If you need them to +indicate precedence, you should use nested ``if`` tags. + +.. versionadded:: 1.2 + + +``if`` tags may also use the operators ``==``, ``!=``, ``<``, ``>``, +``<=``, ``>=`` and ``in`` which work as follows: + + +``==`` operator +^^^^^^^^^^^^^^^ + +Equality. Example:: + + {% if somevar == "x" %} + This appears if variable somevar equals the string "x" + {% endif %} + +``!=`` operator +^^^^^^^^^^^^^^^ + +Inequality. Example:: + + {% if somevar != "x" %} + This appears if variable somevar does not equal the string "x", + or if somevar is not found in the context + {% endif %} + +``<`` operator +^^^^^^^^^^^^^^ + +Less than. Example:: + + {% if somevar < 100 %} + This appears if variable somevar is less than 100. + {% endif %} + +``>`` operator +^^^^^^^^^^^^^^ + +Greater than. Example:: + + {% if somevar > 0 %} + This appears if variable somevar is greater than 0. + {% endif %} + +``<=`` operator +^^^^^^^^^^^^^^^ + +Less than or equal to. Example:: + + {% if somevar <= 100 %} + This appears if variable somevar is less than 100 or equal to 100. + {% endif %} + +``>=`` operator +^^^^^^^^^^^^^^^ + +Greater than or equal to. Example:: + + {% if somevar >= 1 %} + This appears if variable somevar is greater than 1 or equal to 1. + {% endif %} + +``in`` operator +^^^^^^^^^^^^^^^ + +Contained within. This operator is supported by many Python containers to test +whether the given value is in the container. The following are some examples of +how ``x in y`` will be interpreted:: + + {% if "bc" in "abcdef" %} + This appears since "bc" is a substring of "abcdef" + {% endif %} + + {% if "hello" in greetings %} + If greetings is a list or set, one element of which is the string + "hello", this will appear. {% endif %} -Multiple uses of the same logical operator are fine, as long as you use the -same operator. For example, this is valid:: + {% if user in users %} + If users is a QuerySet, this will appear if user is an + instance that belongs to the QuerySet. + {% endif %} + + +The comparison operators cannot be 'chained' like in Python or in mathematical +notation. For example, instead of using:: + + {% if a > b > c %} (WRONG) + +you should use:: + + {% if a > b and b > c %} + + +Filters +^^^^^^^ + +You can also use filters in the ``if`` expression. For example:: + + {% if messages|length >= 100 %} + You have lots of messages today! + {% endif %} + +Complex expressions +^^^^^^^^^^^^^^^^^^^ + +All of the above can be combined to form complex expressions. For such +expressions, it can be important to know how the operators are grouped when the +expression is evaluated - that is, the precedence rules. The precedence of the +operators, from lowest to highest, is as follows: + + * ``or`` + * ``and`` + * ``not`` + * ``in`` + * ``==``, ``!=``, ``<``, ``>``,``<=``, ``>=`` + +(This follows Python exactly). So, for example, the following complex if tag: + + {% if a == b or c == d and e %} + +...will be interpreted as: + +.. code-block:: python + + (a == b) or ((c == d) and e) + +If you need different precedence, you will need to use nested if tags. Sometimes +that is better for clarity anyway, for the sake of those who do not know the +precedence rules. - {% if athlete_list or coach_list or parent_list or teacher_list %} .. templatetag:: ifchanged @@ -427,6 +559,9 @@ You cannot check for equality with Python objects such as ``True`` or ``False``. If you need to test if something is true or false, use the ``if`` tag instead. +.. versionadded:: 1.2 + An alternative to the ``ifequal`` tag is to use the :ttag:`if` tag and the ``==`` operator. + .. templatetag:: ifnotequal ifnotequal @@ -434,6 +569,9 @@ ifnotequal Just like ``ifequal``, except it tests that the two arguments are not equal. +.. versionadded:: 1.2 + An alternative to the ``ifnotequal`` tag is to use the :ttag:`if` tag and the ``!=`` operator. + .. templatetag:: include include diff --git a/docs/releases/1.2.txt b/docs/releases/1.2.txt index 58189de362..22560a1f1f 100644 --- a/docs/releases/1.2.txt +++ b/docs/releases/1.2.txt @@ -42,6 +42,15 @@ changes that developers must be aware of: * All of the CSRF has moved from contrib to core (with backwards compatible imports in the old locations, which are deprecated). +:ttag:`if` tag changes +---------------------- + +Due to new features in the :ttag:`if` template tag, it no longer accepts 'and', +'or' and 'not' as valid **variable** names. Previously that worked in some +cases even though these strings were normally treated as keywords. Now, the +keyword status is always enforced, and template code like ``{% if not %}`` or +``{% if and %}`` will throw a TemplateSyntaxError. + ``LazyObject`` -------------- @@ -196,3 +205,37 @@ messaging, for both anonymous and authenticated clients. The messages framework replaces the deprecated user message API and allows you to temporarily store messages in one request and retrieve them for display in a subsequent request (usually the next one). + +'Smart' if tag +-------------- + +The :ttag:`if` tag has been upgraded to be much more powerful. First, support +for comparison operators has been added. No longer will you have to type: + +.. code-block:: html+django + + {% ifnotequal a b %} + ... + {% endifnotequal %} + +...as you can now do: + +.. code-block:: html+django + + {% if a != b %} + ... + {% endif %} + +The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=`` and +``in``, all of which work like the Python operators, in addition to ``and``, +``or`` and ``not`` which were already supported. + +Also, filters may now be used in the ``if`` expression. For example: + +.. code-block:: html+django + + <div + {% if user.email|lower == message.recipient|lower %} + class="highlight" + {% endif %} + >{{ message }}</div> diff --git a/docs/topics/templates.txt b/docs/topics/templates.txt index 1c8b63c61e..41cb94a56d 100644 --- a/docs/topics/templates.txt +++ b/docs/topics/templates.txt @@ -187,8 +187,8 @@ tags: <li>{{ athlete.name }}</li> {% endfor %} </ul> - - :ttag:`if` and :ttag:`else` + + :ttag:`if` and ``else`` Evaluates a variable, and if that variable is "true" the contents of the block are displayed:: @@ -200,20 +200,15 @@ tags: In the above, if ``athlete_list`` is not empty, the number of athletes will be displayed by the ``{{ athlete_list|length }}`` variable. - - :ttag:`ifequal` and :ttag:`ifnotequal` - Display some contents if two arguments are or are not equal. For example:: - {% ifequal athlete.name coach.name %} - ... - {% endifequal %} + You can also use filters and various operators in the ``if`` tag:: - Or:: + {% if athlete_list|length > 1 %} + Team: {% for athlete in athlete_list %} ... {% endfor %} + {% else %} + Athlete: {{ athlete_list.0.name }} + {% endif %} - {% ifnotequal athlete.name "Joe" %} - ... - {% endifnotequal %} - :ttag:`block` and :ttag:`extends` Set up `template inheritance`_ (see below), a powerful way of cutting down on "boilerplate" in templates. |
