DTML is the Document Template Markup Language, a handy presentation and templating language that comes with Zope. This Appendix is a reference to all of DTMLs markup tags and how they work.
The ‘call’ tag lets you call a method without inserting the results into the DTML output.
‘call’ tag syntax:
<dtml-call Variable|expr="Expression">
If the call tag uses a variable, the methods arguments are passed automatically by DTML just as with the ‘var’ tag. If the method is specified in a expression, then you must pass the arguments yourself.
Calling by variable name:
<dtml-call UpdateInfo>
This calls the ‘UpdateInfo’ object automatically passing arguments.
Calling by expression:
<dtml-call expr="RESPONSE.setHeader('content-type', 'text/plain')">
The comment tag lets you document your DTML with comments. You can also use it to temporarily disable DTML tags by commenting them out.
‘comment’ tag syntax:
<dtml-comment>
</dtml-comment>
The ‘comment’ tag is a block tag. The contents of the block are not executed, nor are they inserted into the DTML output.
Documenting DTML:
<dtml-comment>
This content is not executed and does not appear in the output.
</dtml-comment>
Commenting out DTML:
<dtml-comment>
This DTML is disabled and will not be executed.
<dtml-call someMethod>
</dtml-comment>
Zope still validates the DTML inside the comment block and will not save any comments that are not valid DTML. It is also not possible to comment in a way that breaks code flow, for example you cannot inproperly nest a comment and a dtml-in.
DTML utility functions provide some Python built-in functions and some DTML-specific functions.
The ‘if’ tags allows you to test conditions and to take different actions depending on the conditions. The ‘if’ tag mirrors Python’s ‘if/elif/else’ condition testing statements.
If tag syntax:
<dtml-if ConditionVariable|expr="ConditionExpression">
[<dtml-elif ConditionVariable|expr="ConditionExpression">]
...
[<dtml-else>]
</dtml-if>
The ‘if’ tag is a block tag. The ‘if’ tag and optional ‘elif’ tags take a condition variable name or a condition expression, but not both. If the condition name or expression evaluates to true then the ‘if’ block is executed. True means not zero, an empty string or an empty list. If the condition variable is not found then the condition is considered false.
If the initial condition is false, each ‘elif’ condition is tested in turn. If any ‘elif’ condition is true, its block is executed. Finally the optional ‘else’ block is executed if none of the ‘if’ and ‘elif’ conditions were true. Only one block will be executed.
Testing for a variable:
<dtml-if snake>
The snake variable is true
</dtml-if>
Testing for expression conditions:
<dtml-if expr="num > 5">
num is greater than five
<dtml-elif expr="num < 5">
num is less than five
<dtml-else>
num must be five
</dtml-if>
The ‘in’ tag gives you powerful controls for looping over sequences and performing batch processing.
‘in’ tag syntax:
<dtml-in SequenceVariable|expr="SequenceExpression">
[<dtml-else>]
</dtml-in>
a commenting identifier at the end tag is allowed and will be ignored like:
</dtml-in my_short_sequ_name>
same for ‘</dtml-if>’ and ‘</dtml-let>’
The ‘in’ block is repeated once for each item in the sequence variable or sequence expression. The current item is pushed on to the DTML namespace during each executing of the ‘in’ block.
If there are no items in the sequence variable or expression, the optional ‘else’ block is executed.
The desired minimum batch size. This controls how sequences are split into batches. If a batch smaller than the orphan size would occur, then no split is performed, and a batch larger than the batch size results.
For example, if the sequence size is 12, the batch size is 10 the orphan size is 3, then the result is one batch with all 12 items since splitting the items into two batches would result in a batch smaller than the orphan size.
The default value is 0.
These variables describe the current item.
These variable summarize information about numeric item variables. To use these variable you must loop over objects (like database query results) that have numeric variables.
These variables allow you to track changes in current item variables.
Looping over sub-objects:
<dtml-in objectValues>
title: <dtml-var title><br>
</dtml-in>
Looping over two sets of objects, using prefixes:
<dtml-let rows="(1,2,3)" cols="(4,5,6)">
<dtml-in rows prefix="row">
<dtml-in cols prefix="col">
<dtml-var expr="row_item * col_item"><br>
<dtml-if col_end>
<dtml-var expr="col_total_item * row_mean_item">
</dtml-if>
</dtml-in>
</dtml-in>
</dtml-let>
Looping over a list of ‘(key, value)’ tuples:
<dtml-in objectItems>
id: <dtml-var sequence-key>, title: <dtml-var title><br>
</dtml-in>
Creating alternate colored table rows:
<table>
<dtml-in objectValues>
<tr <dtml-if sequence-odd>bgcolor="#EEEEEE"
<dtml-else>bgcolor="#FFFFFF"
</dtml-if>>
<td><dtml-var title></td>
</tr>
</dtml-in>
</table>
Basic batch processing:
<p>
<dtml-in largeSequence size=10 start=start previous>
<a href="<dtml-var absolute_url>
<dtml-var sequence-query>start=<dtml-var previous-sequence-start-number>">
Previous
</a>
</dtml-in>
<dtml-in largeSequence size=10 start=start next>
<a href="<dtml-var absolute_url>
<dtml-var sequence-query>start=<dtml-var next-sequence-start-number>">
Next
</a>
</dtml-in>
</p>
<p>
<dtml-in largeSequence size=10 start=start>
<dtml-var sequence-item>
</dtml-in>
</p>
This example creates Previous and Next links to navigate between batches. Note, by using ‘sequence-query’, you do not lose any GET variables as you navigate between batches.
The ‘let’ tag defines variables in the DTML namespace.
‘let’ tag syntax:
<dtml-let [Name=Variable][Name="Expression"]...>
</dtml-let>
The ‘let’ tag is a block tag. Variables are defined by tag arguments. Defined variables are pushed onto the DTML namespace while the ‘let’ block is executed. Variables are defined by attributes. The ‘let’ tag can have one or more attributes with arbitrary names. If the attributes are defined with double quotes they are considered expressions, otherwise they are looked up by name. Attributes are processed in order, so later attributes can reference, and/or overwrite earlier ones.
Basic usage:
<dtml-let name="'Bob'" ids=objectIds>
name: <dtml-var name>
ids: <dtml-var ids>
</dtml-let>
Using the ‘let’ tag with the ‘in’ tag:
<dtml-in expr="(1,2,3,4)">
<dtml-let num=sequence-item
index=sequence-index
result="num*index">
<dtml-var num> * <dtml-var index> = <dtml-var result>
</dtml-let>
</dtml-in>
This yields:
1 * 0 = 0
2 * 1 = 2
3 * 2 = 6
4 * 3 = 12
The ‘mime’ tag allows you to create MIME encoded data. It is chiefly used to format email inside the ‘sendmail’ tag.
‘mime’ tag syntax:
<dtml-mime>
[<dtml-boundry>]
...
</dtml-mime>
The ‘mime’ tag is a block tag. The block is can be divided by one or more ‘boundry’ tags to create a multi-part MIME message. ‘mime’ tags may be nested. The ‘mime’ tag is most often used inside the ‘sendmail’ tag.
Both the ‘mime’ and ‘boundry’ tags have the same attributes.
Sending a file attachment:
<dtml-sendmail>
To: <dtml-var recipient>
Subject: Resume
<dtml-mime type="text/plain" encode="7bit">
Hi, please take a look at my resume.
<dtml-boundary type="application/octet-stream" disposition="attachment"
encode="base64" filename_expr="resume_file.getId()"><dtml-var expr="resume_file.read()"></dtml-mime>
</dtml-sendmail>
The ‘raise’ tag raises an exception, mirroring the Python ‘raise’ statement.
‘raise’ tag syntax:
<dtml-raise ExceptionName|ExceptionExpression>
</dtml-raise>
The ‘raise’ tag is a block tag. It raises an exception. Exceptions can be an exception class or a string. The contents of the tag are passed as the error value.
Raising a KeyError:
<dtml-raise KeyError></dtml-raise>
Raising an HTTP 404 error:
<dtml-raise NotFound>Web Page Not Found</dtml-raise>
The ‘return’ tag stops executing DTML and returns data. It mirrors the Python ‘return’ statement.
‘return’ tag syntax:
<dtml-return ReturnVariable|expr="ReturnExpression">
Stops execution of DTML and returns a variable or expression. The DTML output is not returned. Usually a return expression is more useful than a return variable. Scripts largely obsolete this tag.
Examples
Returning a variable:
<dtml-return result>
Returning a Python dictionary:
<dtml-return expr="{'hi':200, 'lo':5}">
The ‘sendmail’ tag sends an email message using SMTP.
‘sendmail’ tag syntax:
<dtml-sendmail>
</dtml-sendmail>
The ‘sendmail’ tag is a block tag. It either requires a ‘mailhost’ or a ‘smtphost’ argument, but not both. The tag block is sent as an email message. The beginning of the block describes the email headers. The headers are separated from the body by a blank line. Alternately the ‘To’, ‘From’ and ‘Subject’ headers can be set with tag arguments.
Sending an email message using a Mail Host:
<dtml-sendmail mailhost="mailhost">
To: <dtml-var recipient>
From: <dtml-var sender>
Subject: <dtml-var subject>
Dear <dtml-var recipient>,
You order number <dtml-var order_number> is ready.
Please pick it up at your soonest convenience.
</dtml-sendmail>
The ‘sqlgroup’ tag formats complex boolean SQL expressions. You can use it along with the ‘sqltest’ tag to build dynamic SQL queries that tailor themselves to the environment. This tag is used in SQL Methods.
‘sqlgroup’ tag syntax:
<dtml-sqlgroup>
[<dtml-or>]
[<dtml-and>]
...
</dtml-sqlgroup>
The ‘sqlgroup’ tag is a block tag. It is divided into blocks with one or more optional ‘or’ and ‘and’ tags. ‘sqlgroup’ tags can be nested to produce complex logic.
Sample usage:
select * from employees
<dtml-sqlgroup where>
<dtml-sqltest salary op="gt" type="float" optional>
<dtml-and>
<dtml-sqltest first type="nb" multiple optional>
<dtml-and>
<dtml-sqltest last type="nb" multiple optional>
</dtml-sqlgroup>
If ‘first’ is ‘Bob’ and ‘last’ is ‘Smith, McDonald’ it renders:
select * from employees
where
(first='Bob'
and
last in ('Smith', 'McDonald')
)
If ‘salary’ is 50000 and ‘last’ is ‘Smith’ it renders:
select * from employees
where
(salary > 50000.0
and
last='Smith'
)
Nested ‘sqlgroup’ tags:
select * from employees
<dtml-sqlgroup where>
<dtml-sqlgroup>
<dtml-sqltest first op="like" type="nb">
<dtml-and>
<dtml-sqltest last op="like" type="nb">
</dtml-sqlgroup>
<dtml-or>
<dtml-sqltest salary op="gt" type="float">
</dtml-sqlgroup>
Given sample arguments, this template renders to SQL like so:
select * form employees
where
(
(
name like 'A*'
and
last like 'Smith'
)
or
salary > 20000.0
)
The ‘sqltest’ tag inserts a condition test into SQL code. It tests a column against a variable. This tag is used in SQL Methods.
‘sqltest’ tag syntax:
<dtml-sqltest Variable|expr="VariableExpression">
The ‘sqltest’ tag is a singleton. It inserts a SQL condition test statement. It is used to build SQL queries. The ‘sqltest’ tag correctly escapes the inserted variable. The named variable or variable expression is tested against a SQL column using the specified comparison operation.
The comparison operation. Valid comparisons include:
The comparison defaults to equal to. If the comparison is not recognized it is used anyway. Thus you can use comparisons such as ‘like’.
Basic usage:
select * from employees
where <dtml-sqltest name type="nb">
If the ‘name’ variable is ‘Bob’ then this renders:
select * from employees
where name = 'Bob'
Multiple values:
select * from employees
where <dtml-sqltest empid type=int multiple>
If the ‘empid’ variable is ‘(12,14,17)’ then this renders:
select * from employees
where empid in (12, 14, 17)
The ‘sqlvar’ tag safely inserts variables into SQL code. This tag is used in SQL Methods.
‘sqlvar’ tag syntax:
<dtml-sqlvar Variable|expr="VariableExpression">
The ‘sqlvar’ tag is a singleton. Like the ‘var’ tag, the ‘sqlvar’ tag looks up a variable and inserts it. Unlike the var tag, the formatting options are tailored for SQL code.
Basic usage:
select * from employees
where name=<dtml-sqlvar name type="nb">
This SQL quotes the ‘name’ string variable.
The ‘tree’ tag displays a dynamic tree widget by querying Zope objects.
‘tree’ tag syntax:
<dtml-tree [VariableName|expr="VariableExpression"]>
</dtml-tree>
The ‘tree’ tag is a block tag. It renders a dynamic tree widget in HTML. The root of the tree is given by variable name or expression, if present, otherwise it defaults to the current object. The ‘tree’ block is rendered for each tree node, with the current node pushed onto the DTML namespace.
Tree state is set in HTTP cookies. Thus for trees to work, cookies must be enabled. Also you can only have one tree per page.
You can control the tree tag by setting these variables.
Display a tree rooted in the current object:
<dtml-tree>
<dtml-var title_or_id>
</dtml-tree>
Display a tree rooted in another object, using a custom branches method:
<dtml-tree expr="folder.object" branches="objectValues">
Node id : <dtml-var getId>
</dtml-tree>
The ‘try’ tag allows exception handling in DTML, mirroring the Python ‘try/except’ and ‘try/finally’ constructs.
The ‘try’ tag has two different syntaxes, ‘try/except/else’ and ‘try/finally’.
‘try/except/else’ Syntax:
<dtml-try>
<dtml-except [ExceptionName] [ExceptionName]...>
...
[<dtml-else>]
</dtml-try>
The ‘try’ tag encloses a block in which exceptions can be caught and handled. There can be one or more ‘except’ tags that handles zero or more exceptions. If an ‘except’ tag does not specify an exception, then it handles all exceptions.
When an exception is raised, control jumps to the first ‘except’ tag that handles the exception. If there is no ‘except’ tag to handle the exception, then the exception is raised normally.
If no exception is raised, and there is an ‘else’ tag, then the ‘else’ tag will be executed after the body of the ‘try’ tag.
The ‘except’ and ‘else’ tags are optional.
‘try/finally’ Syntax:
<dtml-try>
<dtml-finally>
</dtml-try>
The ‘finally’ tag cannot be used in the same ‘try’ block as the ‘except’ and ‘else’ tags. If there is a ‘finally’ tag, its block will be executed whether or not an exception is raised in the ‘try’ block.
Inside the ‘except’ block these variables are defined.
Catching a math error:
<dtml-try>
<dtml-var expr="1/0">
<dtml-except ZeroDivisionError>
You tried to divide by zero.
</dtml-try>
Returning information about the handled exception:
<dtml-try>
<dtml-call dangerousMethod>
<dtml-except>
An error occurred.
Error type: <dtml-var error_type>
Error value: <dtml-var error_value>
</dtml-try>
Using finally to make sure to perform clean up regardless of whether an error is raised or not:
<dtml-call acquireLock>
<dtml-try>
<dtml-call someMethod>
<dtml-finally>
<dtml-call releaseLock>
</dtml-try>
The ‘unless’ tag provides a shortcut for testing negative conditions. For more complete condition testing use the ‘if’ tag.
‘unless’ tag syntax:
<dtml-unless ConditionVariable|expr="ConditionExpression">
</dtml-unless>
The ‘unless’ tag is a block tag. If the condition variable or expression evaluates to false, then the contained block is executed. Like the ‘if’ tag, variables that are not present are considered false.
Testing a variable:
<dtml-unless testMode>
<dtml-call dangerousOperation>
</dtml-unless>
The block will be executed if ‘testMode’ does not exist, or exists but is false.
The ‘var’ tags allows you insert variables into DTML output.
‘var’ tag syntax:
<dtml-var Variable|expr="Expression">
The ‘var’ tag is a singleton tag. The ‘var’ tag finds a variable by searching the DTML namespace which usually consists of current object, the current object’s containers, and finally the web request. If the variable is found, it is inserted into the DTML output. If not found, Zope raises an error.
‘var’ tag entity syntax:
&dtml-variableName;
Entity syntax is a short cut which inserts and HTML quotes the variable. It is useful when inserting variables into HTML tags.
‘var’ tag entity syntax with attributes:
&dtml.attribute1[.attribute2]...-variableName;
To a limited degree you may specify attributes with the entity syntax. You may include zero or more attributes delimited by periods. You cannot provide arguments for attributes using the entity syntax. If you provide zero or more attributes, then the variable is not automatically HTML quoted. Thus you can avoid HTML quoting with this syntax, ‘&dtml.-variableName;’.
Format a variable. Zope provides a few built-in formats including C-style format strings. For more information on C-style format strings see the Python Library Reference. If the format string is not a built-in format, then it is assumed to be a method of the object, and it called.
Inserting a simple variable into a document:
<dtml-var standard_html_header>
Truncation:
<dtml-var colors size=10 etc=", etc.">
will produce the following output if colors is the string ‘red yellow green’:
red yellow, etc.
C-style string formatting:
<dtml-var expr="23432.2323" fmt="%.2f">
renders to:
23432.23
Inserting a variable, link, inside an HTML ‘A’ tag with the entity syntax:
<a href="&dtml-link;">Link</a>
Inserting a link to a document ‘doc’, using entity syntax with attributes:
<a href="&dtml.url-doc;"><dtml-var doc fmt="title_or_id"></a>
This creates an HTML link to an object using its URL and title. This example calls the object’s ‘absolute_url’ method for the URL (using the ‘url’ attribute) and its ‘title_or_id’ method for the title.
The ‘with’ tag pushes an object onto the DTML namespace. Variables will be looked up in the pushed object first.
‘with’ tag syntax:
<dtml-with Variable|expr="Expression">
</dtml-with>
The ‘with’ tag is a block tag. It pushes the named variable or variable expression onto the DTML namespace for the duration of the ‘with’ block. Thus names are looked up in the pushed object first.
Looking up a variable in the REQUEST:
<dtml-with REQUEST only>
<dtml-if id>
<dtml-var id>
<dtml-else>
'id' was not in the request.
</dtml-if>
</dtml-with>
Pushing the first child on the DTML namespace:
<dtml-with expr="objectValues()[0]">
First child's id: <dtml-var id>
</dtml-with>