Subsections


3. Blocks


3.1 BEGIN BLOCK Loop

A simple loop is called BLOCK. Designers do not need to know anything about iterators in order to use BLOCKs which makes them simpler to understand. Each BLOCK has to end with an END BLOCK. Inside a block variables of the current run are used like child objects of the block.

The developer simply assigns variables to a run of the block. He does so with the function assign_block_vars(). It takes two arguments. The first one is the BLOCKs name and the second one is a dict with variables. Its format is the same as the format for the dict used in assign_vars().

This is a simple example:

beispiel.tpl

{BEGIN BLOCK number}
Number: {number.VALUE}
{END BLOCK number}

beispiel.py

from tplEngine import *
template = TplTemplate('beispiel', 'beispiel.tpl')

for i in range(5):
    template.assign_block_vars('number', {'VALUE': i+1})
    
print template.get_executed()

Console

$ python beispiel.py

Number: 1
Number: 2
Number: 3
Number: 4
Number: 5


3.2 LENGTH And RUN

To find out how many runs a BLOCK has you can use the variable LENGTH. It's a child object of every BLOCK which is also accessible from outside. So to get a BLOCK's length you do not have to be inside the BLOCK.

If need to know the current run you can use the child object RUN. You can only use it inside a BLOCK. RUN is 0 for the first run.

beispiel.tpl

There are {char.LENGTH} characters.
{BEGIN BLOCK char}
Run:  {char.RUN + 1}
Char: {char.CHAR}
-------
{END BLOCK char}

beispiel.py

from tplEngine import *
template = TplTemplate('beispiel', 'beispiel.tpl')

chars = ['a', 'b', 'c', 'd', 'e']
for char in chars:
    template.assign_block_vars('char', {'CHAR': char})
    
print template.get_executed()

Console

$ python beispiel.py
There are 5 characters.
Run:  1
Char: a
-------
Run:  2
Char: b
-------
Run:  3
Char: c
-------
Run:  4
Char: d
-------
Run:  5
Char: e
-------


3.3 Nested BLOCKs

You can nest blocks unlimited. Each subblock is a child object of its parent BLOCK. The child BLOCK's LENGTH can not be accessed from the top level but only inside the parent BLOCK.

beispiel.tpl

There are {group.LENGTH} groups.
{BEGIN BLOCK group}
    {group.NAME}
    There are {group.user.LENGTH} users in this group.
    {BEGIN BLOCK group.user}
        NAME: {group.user.NAME}
    {END BLOCK group.user}
{END BLOCK group}

beispiel.py

from tplEngine import *
template = TplTemplate('beispiel', 'beispiel.tpl')

groups = ['Registered Users', 'Administrators']
users = {0: ['Peter', 'Paul', 'Jesse'], 1: ['Simon', 'George']}

for i in range(len(groups)):
    template.assign_block_vars('group', {'NAME': groups[i]})
    for user in users[i]:
        template.assign_block_vars('group.user', {'NAME': user})
    
print template.get_executed()

Console

$ python beispiel.py
There are 2 groups.
    Registered Users
    There are 3 users in this group.
        NAME: Peter
        NAME: Paul
        NAME: Jesse
    Administrators
    There are 2 users in this group.
        NAME: Simon
        NAME: George


3.4 Multiple BLOCK Assignments

If you need to assign values to a BLOCK more than once per run you have to use a different first parameter for assign_block_vars(). You have to assign a dict to it which has the BLOCK names as keys and the run you're assigning to has values. I will use the last example to demonstrate this.

beispiel.tpl

{BEGIN BLOCK group}
    {group.NAME}
    {BEGIN BLOCK group.user}
        NAME: {group.user.NAME}
        AGE:  {group.user.AGE}
    {END BLOCK group.user}
{END BLOCK group}

beispiel.py

from tplEngine import *
template = TplTemplate('beispiel', 'beispiel.tpl')

groups = ['Registered Users', 'Administrators']
users = {0: [('Peter', 20), ('Paul', 30), ('Jesse', 25)], 1: [('Simon', 40), ('George', 35)]}

for i in range(len(groups)):
    template.assign_block_vars(
        {'group':i},
        {'NAME': groups[i]})
    for j in range(len(users[i])):
        template.assign_block_vars(
            {'group':i,'user':j},
            {'NAME': users[i][j][0],
             'AGE': users[i][j][1]})
    
print template.get_executed()

Console

$ python beispiel.py
    Registered Users
        NAME: Peter
        AGE:  20
        NAME: Paul
        AGE:  30
        NAME: Jesse
        AGE:  25
    Administrators
        NAME: Simon
        AGE:  40
        NAME: George
        AGE:  35

Using this assignment style you can also overwrite already assigned runs. If you use the string assignment it is automatically converted to a dict with the run -1. So you can assign to the next row by using -1 as a key.


3.5 RECURSION

Now you may wonder, how do I go about creating tree menus with unlimited depth? You can do it! You have to use recursion in order to use unlimited nesting.

You start a recursive BLOCK with BEGIN RECURSION and you end it with END RECURSION. You place a RECURSE where you want to insert the child object. To find out whether the child object has any elements you can use LENGTH as normal. Maybe an example will help to make this understandable.

beispiel.tpl

{BEGIN RECURSION item}
    {item.NAME} ({item.item.LENGTH} child elements)
    {RECURSE item}
{END RECURSION item}

beispiel.py

from tplEngine import *
template = TplTemplate('beispiel', 'beispiel.tpl')

items = [('A', [('A.1', [])]),
    ('B', [('B.1', [('B.1.1', []), ('B.1.2', []), ('B.1.3', [])]), ('B.2', []), ('B.3', [('B.3.1', [])])]),
    ('C', [('C.1', [('C.1.1', [])]), ('C.2', [])])]

def assign_recursive(item, template, depth):
    template.assign_block_vars('item' + ('.item'*depth),{'NAME':item[0]})
    for new_item in item[1]:
        assign_recursive(new_item, template, depth+1)

for item in items:
    assign_recursive(item, template, 0)
    
print template.get_executed()

Console

$ python beispiel.py

    A (1 child elements)
    A.1 (0 child elements)
    B (3 child elements)
    B.1 (3 child elements)
    B.1.1 (0 child elements)
    B.1.2 (0 child elements)
    B.1.3 (0 child elements)
    B.2 (0 child elements)
    B.3 (1 child elements)
    B.3.1 (0 child elements)
    C (2 child elements)
    C.1 (1 child elements)
    C.1.1 (0 child elements)
    C.2 (0 child elements)

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