Basic syntax
The web2py template language supports all Python control structures. Here we provide some examples of each of them. They can be nested according to usual programming practice.
for...in
In templates you can loop over any iterable object:
{{items = ['a', 'b', 'c']}}
<ul>
{{for item in items:}}<li>{{=item}}</li>{{pass}}
</ul>
which produces:
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
Here items
is any iterable object such as a Python list, Python tuple, or Rows object, or any object that is implemented as an iterator. The elements displayed are first serialized and escaped.
while
You can create a loop using the while keyword:
{{k = 3}}
<ul>
{{while k > 0:}}<li>{{=k}}{{k = k - 1}}</li>{{pass}}
</ul>
which produces:
<ul>
<li>3</li>
<li>2</li>
<li>1</li>
</ul>
if...elif...else
You can use conditional clauses:
{{
import random
k = random.randint(0, 100)
}}
<h2>
{{=k}}
{{if k % 2:}}is odd{{else:}}is even{{pass}}
</h2>
which produces:
<h2>
45 is odd
</h2>
Since it is obvious that else
closes the first if
block, there is no need for a pass
statement, and using one would be incorrect. However, you must explicitly close the else
block with a pass
.
Recall that in Python “else if” is written elif
as in the following example:
{{
import random
k = random.randint(0, 100)
}}
<h2>
{{=k}}
{{if k % 4 == 0:}}is divisible by 4
{{elif k % 2 == 0:}}is even
{{else:}}is odd
{{pass}}
</h2>
It produces:
<h2>
64 is divisible by 4
</h2>
try...except...else...finally
It is also possible to use try...except
statements in views with one caveat. Consider the following example:
{{try:}}
Hello {{= 1 / 0}}
{{except:}}
division by zero
{{else:}}
no division by zero
{{finally:}}
<br />
{{pass}}
It will produce the following output:
Hello division by zero
<br />
This example illustrates that all output generated before an exception occurs is rendered (including output that preceded the exception) inside the try block. “Hello” is written because it precedes the exception.
def...return
The web2py template language allows the developer to define and implement functions that can return any Python object or a text/html string. Here we consider two examples:
{{def itemize1(link): return LI(A(link, _href="http://" + link))}}
<ul>
{{=itemize1('www.google.com')}}
</ul>
produces the following output:
<ul>
<li><a href="http:/www.google.com">www.google.com</a></li>
</ul>
The function itemize1
returns a helper object that is inserted at the location where the function is called.
Consider now the following code:
{{def itemize2(link):}}
<li><a href="http://{{=link}}">{{=link}}</a></li>
{{return}}
<ul>
{{itemize2('www.google.com')}}
</ul>
It produces exactly the same output as above. In this case, the function itemize2
represents a piece of HTML that is going to replace the web2py tag where the function is called. Notice that there is no ‘=’ in front of the call to itemize2
, since the function does not return the text, but it writes it directly into the response.
There is one caveat: functions defined inside a view must terminate with a return
statement, or the automatic indentation will fail.