Subsections

5. Templating languages: CHTL and CGTL

CherryPy comes with TWO templating languages. They are very similar to each other, but they are used in different situations. They have been designed to be very easy to use, and yet very powerful.

Note that you can also use other templating languages if you want (for instance, there is a HowTo that explains how to use Cheetah), or you can just use plain python to generate your pages.

5.1 Tags

Both languages use only 6 tags: py-eval, py-attr, py-exec, py-code, py-if (with py-else) and py-for.

All tags are used the same way: CherryPyTag="Some Python code". For instance:

py-eval="2*2"
py-exec="a=1"
py-if="2==0"
py-for="i in range(10)"
...

If you want to use double-quotes inside the python code, you need to escape them using a backslash, like this:

py-eval="'I love \"cherry pies\"'"

Let's see what each of these tags is used for:

5.1.1 py-eval

This tag is used to evaluate a Python expression, like this:
Hello, the sum is <py-eval="1+2+3">

This line will be rendered as:

Hello, the sum is 6

What happens is that CherryPy first evaluates the expression (using eval) and then uses str on the result to convert it to a string.

All the CGTL tags can be closed using /> or / >, like this:

<py-eval="'abcd' * 2" />
<py-eval="'Hello, %s' % name"/>

In its CHTL form, the py-eval tag can be used with any pair of opening/closing tags, like this:

<span class=myClass py-eval="2*3"></span>
<a href="myHref" py-eval="'Click here'"></a>
<u py-eval="'I\'m with an underline'"></u>
...

If you don't want to use any HTML tag around the expression, the trick is to use the <div> HTML tag:

This is a long string with a <div py-eval="'variable'"></div> in it

5.1.2 py-attr

This tag is like py-eval, except it's used for HTML tag attributes. The way it is used is as follows:
<td py-attr="'red'" bgColor="">
This will be rendered as
<td bgColor="red">
Note that this is equivalent to:
<td bgColor="<py-eval="'red'">">
But the first syntax is preferred.

5.1.3 py-exec and py-code

These tags are used to execute some Python code. py-exec is used to execute one line of Python code, and py-code is used to execute blocks of Python code. For instance, the following code:
<py-exec="a=2">
<py-code="
    if a==2:
        b=1
    else:
        b==2
">
b equals <py-eval="b">
Will be rendered as:
b equals 1

In the CHTL syntax, both tags have to be embedded in <div> and </div> tags as follow:

<div py-exec="a=2"></div>
<div py-code="
    if a==2:
        b=1
    else:
        b=2
"></div>

If you want to render some data inside the Python code, you must append it to the _page variable:

<html><body>
    Integers from 0 to 9:
    <py-code="
        for i in range(10):
            _page.append("%s "%i)
    ">
</body></html>

This will be rendered as:

<html><body>
    Integers from 0 to 9:
    0 1 2 3 4 5 6 7 8 9
</body></html>

5.1.4 py-if and py-else

These tags are used like if and else in Python. The syntax is as follows:
<py-if="1==1">
    OK
</py-if><py-else>
    Not OK
</py-else>

This will be rendered as

OK

Note that if there is an else clause, the <div py-else> tag must follow the </div> tag closing the <div py-if tag, with no significant characters in between (ie: only separators are allowed)

The CHTL equivalent is:

<div py-if="1==1">
    OK
</div>
<div py-else>
    Not OK
</div>

5.1.5 py-for

This tag is used like for in Python. The syntax is as follows:
<py-for="i in range(10)">
    <py-eval="i">
</py-for>
This will be rendered as
0 1 2 3 4 5 6 7 8 9

Note that you can loop over a list of tuples:

<py-for="i,j in [(0,0), (0,1), (1,0), (1,1)]">
    <py-eval="i+j">
</py-for>
This will be rendered as
0 1 1 2

The CGTL equivalent is:

<div py-for="i,j in [(0,0), (0,1), (1,0), (1,1)]">
    <div py-eval="i+j"></div>
</div>

In a py-for loop, CherryPy sets two handy special variables for you: _index and _end. The former is an integer containing the current number of iterations (from 0 to n-1). The latter contains the total number of iteration minus one.

For instance, if you want to display a list with the first item in bold and the last item underlined, you can use the following code:

<py-exec="myList=[1,5,3,2,5,4,5]">
<py-for="item in myList">
    <py-if="_index==0"><b py-eval="item"></b>
    </py-if><py-else>
        <py-if="_index==_end"><u py-eval="item"></u>
        </py-if><py-else><py-eval="item"></py-else>
        </div>
    </py-else>
</py-for>
This will be rendered as:
<b>1</b> 5 3 2 5 4 <u>5</u>

In the next section, we'll see how to use all these tags together...

5.2 Putting it together

We are going to make a web page that displays a table with all HTML colors. Edit the Hello.cpy file and change it to:

CherryClass Root:
mask:
    def index(self):
        <html><body>
            <a py-attr="request.base+'/webColors'" href="">
                Click here to see a nice table with all web colors
            </a>
        </body></html>
    def webColors(self):
        <html><body>
            <py-exec="codeList=['00', '33', '66', '99', 'CC', 'FF']">
            <table border=1>
            <py-for="r in codeList">
                <py-for="g in codeList">
                    <tr>
                        <py-for="b in codeList">
                            <py-exec="color='#%s%s%s'%(r,g,b)">
                            <td py-attr="color" bgColor="" py-eval="'&nbsp;&nbsp;'+color+'&nbsp;'"></td>
                        </py-for>
                    </tr>
                </py-for>
            </py-for>
        </body></html>

Recompile the file, restart the server and refresh the page in your browser. Click on the link and you should see a nice table with all web colors.

How does it work ?

The webColors method is a pretty straight forward use of the CHTL tags. One more interesting line is:

<a py-attr="request.base+'/webColors'" href="">

request is a global variable set by CherryPy for each request of a client. It is an instance of a class with several variables. One of them is called base and contains the base URL of the website (in our case: http://localhost:8000). So, the line

<a py-attr="request.base+'/webColors'" href="">
will be rendered as:
<a href="http://localhost:8000/webColors">
This also tells us that when the browser requests the URL http://localhost:8000/webColors, the webColors method of the Root class gets called.

In the next chapter, we'll learn how to use views, functions and when we should use them...

See About this document... for information on suggesting changes.