Document Revision 2.1.0, 2000/03/17
For Zope version 2.1.0
The special namespace variable, _ 8
Creating document templates 21
Using document templates with ZPublisher 22
Showing row number and row data in previous and next batch hyperlinks. 37
Showing information about multiple batches 39
TABLE 1. Expression examples 8
TABLE 2. Available attributes in the special variable, _ 9
TABLE 3. Attributes defined by the math module 10
TABLE 4. Attributes defined by the random module 11
TABLE 5. Attributes defined by the string module 12
TABLE 6. Attributes defined by the whrandom module 13
TABLE 7. Simplest-case steps for looking up names 15
TABLE 8. Zope-defined Web request variables 16
TABLE 9. Attributes of the REQUEST variable. 16
TABLE 10. Attributes of the RESPONSE variable 17
TABLE 11. CGI-defined Web request variables 17
TABLE 12. Document template classes 21
TABLE 13. Standard document template creation arguments. 21
TABLE 14. Standard arguments for calling document templates. 22
TABLE 15. dtml-var tag attributes 23
TABLE 16. Special formats that may be used with the var tag fmt attribute 24
TABLE 17. C-style specifiers for the fmt attribute 24
TABLE 18. dtml-in tag attributes 30
TABLE 19. Item variables defined by the dtml-in tag 32
TABLE 20. Summary statistic variables defined by the dtml-in tag 33
TABLE 21. Special variables for group processing 33
TABLE 22. Batch-processing variables 34
TABLE 23. Attributes of batch objects used when iterating over next-batches and previous-batches variables. 34
TABLE 24. Query strings and previous batch URL and next batch URL for the batches shown in figure 7 37
TABLE 25. dtml-tree tag attributes. 51
TABLE 26. Variables set by the dtml-tree tag when rendering sub-objects. 52
TABLE 27. Variable that influence the dtml-tree tag 53
TABLE 28. dtml-sendmail tag attributes 55
TABLE 29. dtml-mime tag attributes 56
TABLE 30. Custom formats for date-time data 57
The Zope Document Template Markup Language (DTML) is a facility for generating textual information using a template document and application information stored in Zope. It is used in Zope primarily to generate Hypertext Markup Language (HTML) files, but it can also be used to create other types of textual information. For example, it is used to generate Structured Query Language (SQL) commands in Zope SQL Methods.
The DTML facility is used to convert from document template source text to rendered text. Document template source text consists of ordinary text interspersed with DTML "markup" tags.
The purpose of the DTML Reference is to provide a reference dictionary document for the many DTML tags available in Zope and to help programmers in understanding how to implement DTML. The first portion of the guide describes the syntax of DTML tags and provides a number of simple examples of document template source texts. The second section describes the DTML tags in detail.
The DTML Tag is supported by three syntaxes.1 This includes the DTML document templates, server-side includes and Python string formats. When using document templates from Python, the syntax used depends on the document template class used (or subclasses). The server-side-include new DTML syntax described here is used by the classes DocumentTemplate.HTML and DocumentTemplate.HTMLFile.
The syntax formats are shown below:
<dtml-tag name attribute1="value1" attribute2="value2" ... >
The tag name identifies the tag type. Following the tag name, are typically one or more attributes which indicate where the tag's data is found and how that data is to be inserted. Sometimes, attribute values can be omitted and quotation marks around attribute values can be omitted if the values do not contain a space, tab, new-line character, equal sign or double quotation marks.
<dtml-var name="standard_html_header">
The most common tag is the dtml-var tag. The var tag is used to substitute variable data into text. Suppose we want to create a greeting with the variable, input_name . We might use a document template like the following:
Hello <dtml-var name="input_name" capitalize>!
This example uses two attributes, name and capitalize . The name attribute is used to specify a variable name. Typically, a variable name refers to data in World Wide Web (WWW) requests or properties of Zope objects, like folders. Because of the name attribute's frequent usage, there exists a short-hand version of the name attribute in which the attribute name is omitted:
Hello <dtml-var input_name capitalize>!
When using the short-hand form of the name attribute, the value is the first attribute in the tag and is not enclosed in quotation marks.
A similar short-hand notation exists for the dtml-xpr attribute. The expr attribute is used to provide computational expressions, as in:
This may be shortened by eliminating the attribute name, as in:
Like in the name attribute, the attribute value is the first attribute in the tag and is not enclosed in quotation marks.
The capitalize attribute illustrates the use of an attribute in which a value, or argument, is not defined2. The capitalize attribute indicates that the first letter of the inserted text should be capitalized. Suppose the document template source from the previous example is evaluated with the input name, " world ", then the text output would be:
The dtml-var tag is called a singleton tag , because it does not contain any other tags. Tags which are duplex contain bracketed text which may contain other DTML tags. Duplex tags require a matching end tag . The name of the end tag is the same as the start tag, except that it contains a " / " or an "end " prefix. End tags do not have attributes. A commonly used duplex tag is the dtml-if tag:
<dtml-if input_name>
Hello <dtml-var input_name>.
</dtml-if>
In this example, if the variable, input_name , has not been provided or is an empty string, then the greeting is omitted.
A non-empty tag can also have intermediate tags. These intermediate tags serve to break the non-empty tag into two or more sections. For example the dtml-if tag can use an intermediate dtml-else tag, as in:
<dtml-if input_name>
Hello <dtml-var input_name>.
<dtml-else>
Have we been introduced?
<dtml-endif>
Note that in this case, the alternate prefix of the end tag is used.
Intermediate tags can have attributes, as in:
<dtml-if input_name>
Hello <dtml-var input_name>.
<dtml-elif nick_name>
Hi <dtml-var nick_name>.
<dtml-else>
Have we been introduced?
</dtml-if>
In the example above, there is one non-empty tag, dtml-if that uses two intermediate tags, dtml-elif and dtml-else , and an end tag, /dtml-if .
Any number of line endings, tabs or spaces may be placed between the pound character (#), the tag name, attributes or the end of a tag. This format is still valid for the older versions of Zope and DTML. The server side includes format is <!--#command tag1="value1" tag2="value2"-->. The older versions of Zope used this format for the dtml code. You will still see examples using this syntax. For example, the following are all valid tags which are based on the server side includes format:
<!--#var x--> <!--#var standard_html_footer-->
<!--#var some_really_long_name--.
<!--#var and_another_rather_long_one-->
<!--#if input_name--> <!--#/if-->
This section describes the extended Python string format syntax. The extended Python string format syntax is used by the Python classes DocumentTemplate.String and DocumentTemplate.File. This format is based on the insertion-by-name format strings of Python with additional format characters, '[' and ']' to indicate block boundaries. In addition, attributes may be used within formats to control how insertion is done. For example:
causes the contents of variable 'date' to be inserted using custom format 'DayOfWeek' and with all lower case letters converted to upper case.
Document template strings use an extended form of python string formatting. To insert a named value, simply include text of the form:
where 'name' is the name of the value and ' x ' is a format specification, such as '12.2d' . To introduce a block such as an 'if' or an 'in' or a block continuation, such as an 'else', use '[' as the format specification. To terminate a block, use ']' as the format specification, as in:
%(if input_name)[
Hello %(var input_name size=16 etc="...")s.
%(elif nick_name)[
Hi %(var nick_name capitalize)s.
%(else)[
Have we been introduced?
%(/if)]
In most cases, the tag name, 'var' can be omitted. It must be included when:
- The variable to be inserted is named 'var ' and
- when using the expr attribute:
The previous section described two attributes that are used by most DTML tags, the name and expr attributes. Both of these attributes are used to identify or compute data used by the tag.
The name attribute is used to obtain data by name. The data is looked up using the rules described in the section "Name Lookup" below. The name attribute is special since there exists a shortened version of the attribute, as described in the section "DTML Tag Syntax" above.
When the value of a name attribute is looked up, the value is automatically called, if possible. If the value is a Zope Document or Python document template, it is rendered before being given to the tag that uses the name attribute. For example, most Zope documents begin with a dtml- var tag:
<dtml-var standard_html_header>
standard_html_header is a Zope document which provides standard HTML to be included at the top of every page. When the var tag above is used, the DTML in standard_html_header is rendered and the result is inserted in the current document.
If the value of a name attribute is a function3 that is called with no arguments, then the result of the function call is given to the tag using the name attribute.
When the name attribute is used in the dtml- if , dtml- elif , dtml- unless , dtml- in or dtml- with tag, the value associated with the name is cached, causing references to the name in enclosed text to be faster than the initial reference. This is especially useful when the name refers to a function which is expensive to compute. For example:
<dtml-if reallyExpensiveFunction>
<dtml-var reallyExpensiveFunction>
</dtml-if>
The dtml-var tag uses the cached value for reallyExpensiveFunction . Note that tags, such as dtml-in and dtml-with, which introduce new variables may introduce a new value for the given name, causing the cached value to be overridden.
The expr attribute allows complex expressions to be evaluated. The expression used in an expr attribute is enclosed in double quotation marks. Thus for differentiation, double quotation marks are not allowed within the expression.
The expression syntax is that of the Python4 programming language and is similar to the syntax of other common programming languages like C or Java. Table 1 provides examples of simple expressions by giving the syntax and capabilities of each expression.
Invoke method5 meth of obj with arguments a and b |
|
The variable names used in an expr expression are looked up according to the rules described in "Name Lookup" Reference. Looked up values are not "called" as they are when the name attribute is used. In the expressions found in table 1, the name x , func , a , b , obj , age , and status are variable names, while the name meth and title are object attribute names.
Variable names must begin with a letter and contain only letters, digits, and underscore characters. To access a variable with a name that does not follow these rules, it is necessary to use the special variable, _, described in "The special namespace variable, _" below.
A special variable, _ , is defined for use in expr expressions. The _ variable provides access to the DTML "namespace," which is an object used to look up variables when rendering DTML. The _ variable can be used to look up names directly:
<dtml-if "_['sequence-length'] > 20">
The _ variable is especially useful for accessing variables with names that contain special characters, like dashes in the case above.
Choose a random element from the non-empty sequence seq and return it. |
|
Initialize the random number generator from the integers X, Y and Z. |
|
The _ variable has a method, has_key, which can be used to check whether or not a variable is in the namespace:
<dtml-if "_.has_key('sequence-length')">
Note that when a callable value is looked up with the _ variable, it is called automatically, as is done with the name attribute. In the case where it is undesirable to have the value called automatically, the g etitem method of the _ variable is used to look up the value. The getitem method accepts two arguments, the name to be looked up and a flag indicating whether or not the value is to be returned:
<dtml-var "_.getitem(name, 0)">
When a variable name is used in a DTML tag, such as a dtml-var tag or an expr attribute expression, that name must be resolved. Table See Simplest-case steps for looking up names shows the steps taken to look up data in the simplest case.
When a document template is called from Python, the mapping object and keyword arguments supplied when calling the document template are searched, with keyword arguments taking precedence over the mapping object. |
|
When a document templates is called from Python, attributes, including inherited and acquired attributes, of the client passed in the call to the document template are searched. |
|
If DTML is used in a Zope DTML Method or Document and the variable name is document_id or document_title , then the id or title of the document is used. |
|
Attributes of the folder containing the DTML are searched. Attributes include objects in the contents of the folder, properties of the folder, and other attributes defined by Zope6, such as ZopeTime7 . Folder attributes include the attributes of folders containing the folder, with contained folders taking precedence over containing folders. |
|
Search Zope-defined Web-request data (table See Zope-defined Web request variables). |
|
Search variables named URLn , where n is a digit. URL0 is the Request URL without a query string. URL1 is the same as URL0 except that the last name in the URL is removed. URL2 is the same as URL0 except that the last two names are removed, and so on. For example, if the request URL is http://digicool.com/A/B , then URL0 , URL1 , and URL2 are respectively, http://digicool.com/A/B , http://digicool.com/A and http://digicool.com . URL3 is undefined. |
|
Search CGI-defined Web-request variables. See table See CGI-defined Web request variables for a description of CGI-defined variables. |
|
Search HTTP Headers. A variable name associated with a HTTP header consist of the HTTP header name, converted to upper case, with the Prefix, HTTP_ . For example, a HTTP Referer header, if present, can be accessed using the variable name HTTP_REFERER . |
|
Search variables named BASEn , where n is a digit. BASE0 is the prefix of the request URL up to, but not including, the name of the Zope installation or module published by ZPublisher. BASE1 is the request URL up to and including the name of the Zope installation or module published by ZPublisher. BASE2 is the request URL up to the name following the name of the Zope installation or module published by ZPublisher, and so on. For example, assume that a Zope installation or module published by ZPublisher has the URL: http://digicool.com/Demos/Plutonia and that a request URL is http://digicool.com/Demos/Plutonia/Marketing. BASE0 is http://digicool.com/Demos, BASE1 is http://digicool.com/Demos/Plutonia and BASE2 is http://digicool.com/Demos/Plutonia/Marketing. BASE3 is undefined. |
There are two situations in which the search rules for the simplest case are modified. If a Zope object or Python document template is called within a DTML expr attribute expression, then additional variables may be passed in. Variables passed in take precedence over all variables described in Table 6.
An object that represents an authenticated user. When inserted into a DTML document, the value is the user name. This object currently provides no public attributes. Note that this variable may not be defined in Documents that are not protected by security information. |
|
The path to the object containing the user database folder which contained the definition for the authenticated user. |
|
A sequence of ancestors of the object that was accessed in the current request. For example, if the accessed object is a Document, then PARENTS[0] is the folder containing the document, PARENTS[1] is the folder containing the folder containing the document, and so on. |
|
An object that represents the current request. This object may be used in an expr expression to look up request data, including variables described in this table, CGI-defined variables (table See CGI-defined Web request variables), form variables, cookies, and HTTP headers. In addition, expr expressions may use request attributes defined in table See Attributes of the REQUEST variable. |
|
An object that represents the response to the current request. This object is primarily useful in expr expressions using attributes defined in table See Attributes of the RESPONSE variable. |
|
The URL used to invoke the request without the query string, if any. |
If a HTTP Cookie was included in the request, then this attribute is a dictionary8 containing the cookie data. This allows cookie data to be looked up, even if a cookie name is the same as a form variable or an object attribute name. |
|
If a request was initiated by submitting a form, then the form attribute is a dictionarya containing the form data. This allows form data to be looked up, even if a form name is the same as an object attribute name. |
|
Some DTML tags define additional variables. Variables defined by DTML tags take precedence over variables described in table 6. If tags are nested, variables defined in nested tags take precedence over variables defined in tags that are nested in.
Names may not begin with an underscore, except in the special case of the _variable used in an expr attribute expression.
If a variable lookup yields an object that has security information, then access to the variable is allowed only if the user on whose behalf the DTML is being rendered is allowed to access the object.
Document templates provide a basic level of access control by preventing access to names beginning with an underscore9. Additional control may be provided by providing document templates with a 'validate' method. This would typically be done by subclassing one or more of the DocumentTemplate classes.
If provided, the 'validate' method will be called when objects are accessed as instance attributes or when they are accessed through keyed access in an expression. The 'validate' method will be called with five arguments:
If a document template is called from Zope, then the name-space object will have an attribute AUTHENTICATED_USER that is the user object that was found if Zope authenticated a user.
Zope document objects provide their own validate method that implements the security rules of the Zope application framework.
Document templates are made available using the DocumentTemplate package10. The DocumentTemplate package defines four classes to be used depending on whether source is stored in Python strings or in external files and on whether the HTML server-side include syntax or the extended Python string format syntax is used. The four document template classes are shown in table 11.
Document templates are created by calling one of the classes listed in table 11. The source is passed as the first argument. An optional mapping argument may be provided that contains names to be added to the document template namespace when called and default values. An optional third argument may be provided to specify a namespace attribute for the document template. The standard document template creation arguments are listed in table 12.
In addition to the standard creation arguments, additional keyword arguments may be provided to provide additional names and default values for the document template name-space. For example, in:
results=DocumentTemplate.HTMLFile('results.dtml',
{'table_name': 'search results', 'database': 'data'},
pid=os.getpid(),
time=time.time
)
A document template is created using server-side-include syntax source from an external file named 'results.dtml' and with an initial name space that included the names 'table_name', 'database', 'pid', and 'time'.
To generate text using a document template, the document template must be called. Arguments may be provided to supply an object from which to get data, a mapping object to get data from, or keyword arguments containing additional data. The standard arguments for calling document templates are shown in table 13.
Both of the standard arguments may be omitted. If the mapping argument is to be provided positionally without a client, then a None must be passed as the client value, as in:
return results(None, {'search_results': r})
Keyword arguments may be used to provide values, as in:
return results(search_results=r)
Document templates may be published directly with ZPublisher. ZPublisher treats document templates as if they were Python functions that accept the arguments named ' self ' and ' REQUEST '. The object traversed to get to the document template is passed as the ' self ' argument and the request object is passed as the ' REQUEST ' argument. Typically, document templates are defined as class attributes and passed class instances and request data, so instance and request data can be used to generate text.
Document templates may also be used in Python functions called by document templates, as in:
def getResults(self, key, REQUEST):
result_data=self.search(key)
return self.resultTemplate(selfdocument, REQUEST, search_results=result_data)
Be sure to call the document template. A common mistake is to return the document template directly, as in:
def getResults(self, key, REQUEST):
result_data=self.search(key)
return self.resultTemplate
ZPublisher does not attempt to call an object returned from a published object. Results of calling a published function are simply converted to strings and returned. When a document template is converted to a string, the document template source is returned. In the example above, the document template source, rather than the rendered template is returned.
The dtml- var tag is used to perform simple variable substitutions. A number of attributes are provided to control how text is to be inserted and formatted. The attributes are summarized in table 15.
A custom format is used for the output of objects. The value of a custom format is the method name evaluated upon the object to be inserted. The method should return an object that, when converted to a string, yields the desired text. For example, the DTML source text:
inserts the result of calling the method, DayOfWeek, with the value of the variable date . As the example suggests, the most common use of custom formats in Zope is in the output of date-time data. The appendix A provides a summary of the custom formats available for date-time data.
In addition to custom formats, a few special formats are defined by the var tag that can be used with the fmt attribute. These are summarized in table 16.
Show a numeric value with a dollar symbol and two decimal places. |
|
In addition to custom and special formats, C11-style formats may also be used. A C-style format consists of text containing a single conversion specification. A conversion specification consists of a percent sign, optionally followed by a flag, a field width, a precision value, and a conversion specifier. A description of C-style formats is beyond the scope of this document. For details on C-style formats, see a C-language reference manual. Not all conversion specifiers are supported by DTML. Table 17 summarizes the conversion specifiers that DTML does support.
In some applications, and especially in database applications, data variables may alternate between "good" and "null" or "missing" values. A format that is used for good values may be inappropriate for null values. For this reason, the null attribute can be used to specify text to be inserted for null values. Null values are defined as values which:
For example, when showing a monetary value retrieved from a database that is either an invalid number or a missing value, the following variable insertion might be used:
<dtml-var cost fmt="$%.2d" null='n/a'>
The attributes size and etc can be used to truncate long strings. If the size attribute is specified, then the string to be inserted is truncated at the given length. If a space occurs in the second half of the truncated string, then the string is further truncated to the right-most space. After truncation, the value given for the etc attribute is added to the string. If the etc attribute is not provided, then " ... " is used. For example, if the value of the variable color is "red yellow orange green blue", then the tag:
<dtml-var spam size=10 etc="...">
When a Zope Document is created and no source is given, Zope supplies a default DTML source, as shown in figure 1.
In figure 1, several dtml- var tags are used. The first var tag inserts standard_html_header . Inserted in almost all Zope Documents, the standard_html_header is a Document which provides a standard way to begin HTML documents in a Zope installation. Thus, the inserted Document gives a Zope installation a common "look and feel". The standard_html_header document can be edited to customize a Zope installation and can be overridden in sub-folders to give different parts of a site varying appearances. The document standard_html_footer provides a similar function for the end of Zope documents. The var tags that insert standard_html_header and standard_html_footer illustrate the notion that DTML documents can be called from another DTML document.
The variables title_or_id and title_and_id are methods defined on most Zope objects. The method title_or_id returns the object's title if the title is not blank, otherwise the object's id is returned. The method title_and_id returns the title of an object followed by the id in parentheses if the title is not blank, otherwise the id is returned. In figure 1, the title_or_id and title_and_id methods are applied to the folder containing the document. The example illustrates the use of var tags to insert the results of method calls.
The variables document_id and document_title simply return the id and title of the document.
Occasionally, the text to be included in a document is dependent upon some data. The if tag is provided to support the conditional insertion of text based on DTML variables or expressions. As described in "DTML Tag Syntax", the dtml-if tag has four forms:
The dtml-if tag works in a straightforward manner. The variable or expression given in the dtml-if tag is evaluated. If the variable or expression value is true12, then the text following the dtml-if tag is inserted. If the variable or expression value is false, then for each dtml-elif tag given, the variable or expression given in the dtml-elif tag is evaluated. If an dtml-elif variable or expression value is true, the text following the dtml-elif tag is inserted and none of the following dtml-elif variables or expressions are evaluated. If there are no dtml-elif tags or if all of the dtml-elif tag variable or expression values are false, then the text following the dtml-else tag is inserted. If no dtml-else tag was supplied, then no text is inserted.
The dtml-if and dtml-elif tags support only the standard name and expr attributes. The dtml-else tag accepts no attributes.
In addition to the dtml-if tag, the dtml- unless tag is provided with its associated closing tag, /dtml-unless, to insert text if a condition is false. Like the dtml-if tag, the dtml- unless tag accepts the standard name and expr attributes:
<dtml-unless input_name>
You did not provide a name.
</dtml-unless>
Commonly, it is necessary to insert a sequence of values. Some objects, like Zope SQL Method s, and Confera Topics support searching and a means is needed for iterating over search results.
When creating input forms with select lists, it is sometimes a good idea to store the contents of the list in a folder property so that the list can be edited independently from the input form. In this case, the select list options are inserted into a form by iterating over the list property.
The dtml-in tag is used to iterate over a sequence of objects. For example, an employee directory listing might be created with DTML source like that shown in figure 2. In this example, employees is either a sequence of employees, or a function, such as an Zope SQL Method , that computes a sequence of employees. Each employee has a name and phone attribute. These attributes are accessed using dtml- var tags. An dtml- in tag's sort attribute is used to sort employees by name in the output. The dtml-in tag attributes are listed in table 18.
In the example, an empty table would be displayed if there were no employees. To avoid displaying an empty table a message can be provided indicating that there are no employee by using the in tag in combination with the dtml-if tag, as shown in figure 3. In figure 3, the dtml-if tag is used with the employees variable. Sequences of objects are false if they are empty and true if they are not. If there are no employees, the condition in the dtml-if tag is false and the text following the dtml-else tag is inserted.
In the previous example (figure 2) an dtml- in tag is combined with an dtml-if tag to avoid showing an empty table for an empty sequence of employees. An alternative approach is to use an intermediate dtml-else tag in the dtml-in tag. If an dtml-in tag has an intermediate dtml-else tag, then the text following the dtml-else tag is inserted if the sequence used in the dtml-in tag is empty. Figure 4 shows DTML source which uses an dtml-else tag in the dtml-in tag to avoid showing an empty table. The output from this source is the same as the output from the source shown in figure 3. The source in figure 4 is actually more complex that the source in figure 3. The added complexity is due to the fact that the table header and footer have to be moved inside the dtml-in tag. Furthermore, the insertion of the table header and footer has to be conditioned on whether or not an item is the first item, last item, or neither by using the variables sequence-start and sequence-end (table 19).
When a name attribute is used in an dtml-in tag within an if tag, the sequence is only evaluated once, since the dtml-if tag caches the value associated with a name attribute.
In most cases, it is best to use an dtml-in tag inside an dtml-if tag, as illustrated in figure 3. One case in which it may be best to use an dtml-else tag within an dtml-in tag is when the sequence used by the dtml-in tag is computed using an expr attribute and the computation is expensive. Use of the dtml-else tag in the dtml-in tag avoids having to define and evaluate the expression twice.
When text is inserted using an dtml-in tag, a copy of the text is inserted for each item in the sequence. Tags in the inserted text have access to variables not available outside the dtml-in tag. These include:
In addition, for each of the variables listed in tables 19, 22, and 23 with names ending in "-index", there exist variables whose names end in "-number", "-roman", "-Roman", "-letter", and "-Letter" which are indexed from 1, "i","I", "a", and "A", respectively. The sequence-index variable is used to number items as text is inserted. Variables like sequence-letter and sequence-roman provide numbering using letters and Roman numerals.
There also exist variables ending in "-even" and "-odd", which test whether the sequence index is even or odd. This is useful to display rows more visibly by alternating colors.
Finally, for each of the variables ending in "-index", there are variables whose names end in "-var-xxx", where "xxx" is an element attribute name or key. This is useful when displaying previous- and next-batch information. The construct is also useful if used in an dtml-if tag to test whether or not an attribute is present since the attribute lookup will not be extended to the full document template name space.
The dtml-in tag provides variables (table 20) for accessings. Summary statistics are computed over the entire sequence, not just over the items displayed.
total-nnn 13 |
|
The variance of numeric values computed with a degrees of freedom equal to the (count - 1). |
|
The variance of numeric values computed with a degrees of freedom equal to the count. |
|
The standard deviation of numeric values computed with a degrees of freedom equal |
|
The standard deviation of numeric values computed with a degrees of freedom equal to the count. |
The dtml-in tag defines special variables used for testing when a "grouping" variable changes. These variables begin with the prefix "first-" or "last-". Their value is used to test whether an item is the first or last item in a subsequence of displayed items whose value is the same value for the given item variable.
When displaying a large number of objects, it may be impractical to display all of the data at once. While the approach used in figure 3 is practical for a small group of employees, it is impractical for browsing the employees of a large company.
For this reason, the dtml-in tag provides support for batch processing. Information is displayed in batches. Variables are provided (table 22) to aid in the construction of HTML hyperlinks to other batches.
The batch-processing facilities of the dtml-in tag are quite powerful, but the various options and approaches are complex. For lucidity, take for example a simple table of 36 words (figure 5). The DTML source in figure 6 is used to display this data. The DTML uses an if tag to test for an empty sequence of words. The actual sequence is named w36 . Inside the if tag, there are three dtml-in tags. All three dtml-in tags include the attributes, size with the value 5 and start with the value qs . The size attribute is used to specify a batch size. For example purposes, the batch size is unusually small. The start parameter is used to specify the name of a variable which holds the index of the first element of the sequence to be displayed. If the variable is not defined, then the first batch is displayed. Figure 7 shows the output of the DTML as displayed on a Web browser for the first two and last two batches.
The first of the three dtml-in tags is used to display an HTML hyperlink to a previous batch of data. The previous attribute in the dtml-in tag indicates that only previous-batch data should be displayed. Row data are not displayed. If the first batch is being displayed, then no text is inserted (figure 7 (words 1-5)). The source in the first dtml-in tag uses four variable references. The first retrieves the document_id , which is used as a relative URL name for the document. The second variable reference uses sequence-query to retrieve the request query string which has been modified so that it does not include the variable named in the dtml-in tag start attribute, qs . The sequence-query value also contains the necessary punctuation, ` ? ' and ` & ', so that the document_id , sequence-query and URL-encoded value for the next batch start can be concatenated. The URL-encoded value of the next batch start is " qs= " followed by the variable, previous-sequence-start-number . The variable previous-sequence-size provides the size of the previous batch for display in the hyperlink. Note that the previous (or next) sequence size is not necessarily equal to the batch size.
The DTML source has been split over multiple lines by introducing line breaks within var tags. This is a useful way to break up long lines without causing line-breaks to be included in generated HTML.
The second dtml-in tag simply displays the rows in the batch. The third dtml-in tag is similar to the first dtml-in tag, except that a hyperlink to the next batch, rather than the previous batch, is displayed. Table 24 shows the query string, previous batch URL and next-batch URL for the example shown in figure 7.
Note that in the previous example the size of the last batch is six. This is because the dtml-in tag has a feature which attempts to prevent the display of very small batches by combining them with adjacent batches. Normally, if the number of rows in a batch is less than or equal to two, then it is combined with an adjacent batch. The orphan attribute in the dtml-in tag can be used to provide an alternative setting. The value provided in an orphan attribute is the desired minimum batch size. The default setting for an orphan attribute is 3 (three).
Normally, batches are non-overlapping. For large batch sizes, it is sometimes useful to overlap rows between batches. The overlap attribute in the in tag is used to specify how many rows to overlap between batches. The overlap attribute's default value is 0.
The variables beginning previous-sequence-start- , previous-sequence-end- , next-sequence-start- and next-sequence-end- and ending in index , number , roman , Roman , letter , Letter , and var-xxx , where xxx is a row attribute (or key) name, can be used to label which rows begin and end previous and next batches. This is illustrated in figures 8 and 9, which use various batch insertion variables to label previous and next batches.
Hyperlinks to multiple batches can be provided using the next-batches and previous-batches variables. These variables provide access to sequences of mapping objects containing information about all previous and next batches. Figure 10 implements the use of previous-batches to show hyperlinks to previous batches using starting and ending row numbers and next-batches to show hyperlinks to next batches using starting and ending words. Note that nested dtml-in tags are used to iterate over batch information. The nested dtml-in tags must use the mapping attribute because the items in the sequences, associated with next-batches and previous-batches, are mapping objects.
The dtml-with tag can be used to expand the namespace of a document template by adding attributes (or mapping keys) from an object which already exists in the document template namespace. For example, if a document template is used to display a folder, the contents of a sub-folder can be displayed using a dtml-with tag:
<dtml-with subfolder>
<dtml-var title>
</dtml-with>
In combination dtml-with the namespace method of the special variable, _, the dtml-with tag can be used to add new variables to the DTML name space:
<dtml-with "_.namespace(profit=price-cost, title=product_name+' summary')">
<h3><dtml-var title></h3>
The profit is <dtml-var profit>
</dtml-with>
A common use of the dtml-with tag is to cause request variables to be used before object attributes:
The current id is <dtml-var id>
<dtml-with REQUEST>
The id you entered was <dtml-var id>
</dtml-with>
Normally, document templates are used as methods of objects. Object attributes commonly take precedence over request variables. Using the REQUEST variable in a dtml-with tag causes the request to be searched before other parts of the name space.
The only attribute, unique to the dtml-with tag, prunes the enclosing namespaces when rendering the body of the tag. This is advantageous to prevent acquisition within DTML:
<dtml-with REQUEST only>
<dtml-unless id>
An id was not specified.
Without the only attribute, the above DTML would likely get an id value from the enclosing environment, which, in this example, is unwanted.
The dtml-let tag works like the dtml-with tag. It is more flexible in that it allows you to make multiple assignments; and allows you to chain assignments, using earlier declarations in later assignments.
The dtml-let tag is a new tag that lets you create blocks like:
<dtml-var num> * <dtml-var index> = <dtml-var result>
Notice in the above example, the 'result' variable is based on 'num', and 'index', both of which are assigned in the same dtml-let expression.
The syntax of the dtml-let tag requires that each argument to be evaluated in the head of the dtml-let tag must be separated by a newline. Enclosing an argument in double quotes causes it to be evaluated by the DTML expression machinery ("num*index"). Unquoted arguments are referenced by name.
Evaluation of the dtml-let tag is in sequence. The results of earlier assignments are available in later assignments. Later assignments can also override earlier ones, which can be helpful for longer step-by-step calculations. The variables set are in effect for the life of the dtml-let block.
Sometimes, document templates are used to perform actions in addition to or even instead of displaying results. Methods can be called when evaluating name attributes or in expr attribute expressions. These methods may perform a useful action but produce no output or produce an output which is not needed. The dtml- call tag is provided for evaluating expressions or calling methods that have a useful side effect without inserting any text:
<dtml-call "addDocument('hi','display a greeting','Hello world!')">
In many applications, inputs or other variables need to be checked for validity before actions are performed. DTML provides a convenient means of performing validity checks by using the dtml-raise tag in combination with the if tag. Validity checks are performed with the if tag. The dtml-raise tag is used to report the errors.
The dtml-raise tag has a type attribute for specifying an error type. Like the standard name attribute, the attribute name of the type attribute may be omitted. The error type is a short descriptive name for the error. In addition, there are some standard types, like " Unauthorized " and " Redirect " that are returned as HTTP errors. In particular, " Unauthorized " errors cause a log-in prompt to be displayed on the user's browser.
The dtml-raise tag is a non-empty tag. The source enclosed by the dtml-raise tag is rendered to create an error message. If the rendered text contains any HTML markup, then Zope will display the text as an error message on the browser, otherwise a generic error message is displayed.
Here is a dtml-raise tag example:
<dtml-if "balance >= debit_amount">
<dtml-call "debitAccount(account)">
Your account, <dtml-var account>, has been debited.
<dtml-else>
<dtml-raise type="Insufficient funds">
There is not enough money in account <dtml-account>
to cover the requested debit amount.<p>
</dtml-raise>
</dtml-if>
The dtml-raise tag causes a Zope error to occur. However, there is an important side effect to this error that causes any changes made by a web request to be ignored, assuming that a transactional persistence mechanism, like the Zope Database is being used.
Exceptions are unexpected errors Zope encounters during the rendering of a DTML statement. Once an exception is detected, the normal execution of the DTML stops. Consider the following example:
Cost per unit: $<dtml-var expr="_.float(total_cost/total_units)">
This statement functions normally if total_units is not zero. However, in the event that total_units is zero, a ZeroDivisionError exception is raised indicating an illegal operation. Thus, rather than rendering the DTML, an error message will be returned.
DTML provides the dtml-try tag to catch and handle these problematic exceptions within a block of DTML code. This allows you to anticipate and handle errors yourself, rather than getting a Zope error message whenever an exception occurs.
As an exception handler, the dtml-try tag has two functions. First, if an exception is raised, the dtml-try tag gains control of execution and handles the exception appropriately, and thus avoids returning a Zope error message. Second, the dtml-try tag allows the rendering of any subsequent DMTL to continue.
Within the dtml-try tag are one or more dtml-except tags that identify and handle different exceptions. When an exception is raised, each dtml-except tag is checked in turn to see if it matches the exception's type. The first dtml-except tag to match handles the exception. If no exceptions are given in a dtml-except tag, then the dtml-except tag will match all exceptions.
Implementing the dtml-try tag in the example above would resemble:
<dtml-try>
Cost per unit: $<dtml-var expr="_.float(total_cost/total_units")>
<dtml-except ZeroDivisionError>
If a ZeroDivisionError is raised, control goes to the dtml-except tag, and "Cost per unit: N/A" is rendered. Once the statements of the dtml-except tag finish, execution of DTML continues past the dtml-try block.
DTML's except tags work with Python's class-based exceptions. In addition to matching exceptions by name, the dtml-except tag will match any subclass of the named exception. For example, if ArithmaticError is named in a dtml-except tag, the tag can handle all ArithmaticError subclasses including, ZeroDivisionError.
Inside the body of a dtml-except tag you can access information about the handled exception through several special variables. These variables are:
The dtml-try tag has an optional dtml-else block that is rendered if an exception didn't occur. The exceptions in the else block are not handled by the preceding dtml-except blocks. Implementing the dtml-else tag with the dtml-try tag would be like:
<dtml-except SomeError AnotherError>
The first dtml-except block to match the type of error raised is rendered. If a dtml-except block has no name, then it matches all raised errors. The optional dtml-else block is rendered when no exception occurs in the dtml-try block. Exception in the dtml-else block are not handled by the preceding dtml-except blocks.
In addition to the dtml-else block, the dtml-try tag has the ability to use a dtml-finally block that is always rendered whether an exception occurs or not. The dtml-finally form specifies a cleanup block to be rendered even when a exception occurs. Note, any rendered results are discarded if an exception occurs in either the try or finally blocks. The dtml-finally block is only of any used if you need to clean up something that will not be cleaned up by the transaction abort code. The dtml-finally block will always be called, whether there is an exception or nor and whether a return tage is used or not. If you use a dtml-return tag in the try block, any output of the dtml-finally block is discarded.
<dtml-try> <dtml-finally> </dtml-try>
Important to note, if a exception occurs in the dtml-try block and an exception occurs in the dtml-finally block any information about the first exception is lost. It follows that if a return tag is used in the dtml-try block and an exception occurs in the dtml-finally block, the result returned in the dtml-try block will be lost. Also, if a return tag is used in the dtml-finally block, the result returned in the dtml-try block will be lost as well.
The dtml- comment tag provides a way to exclude source text from the rendered text. The dtml- comment tag is a simple non-empty tag that inserts no text. Further, the source enclosed by a dtml- comment tag is not rendered. Dtml- comment tags can be used to provide explanatory text or to disable parts of the source. Comment tags can be nested. Here is an example:
<dtml-call updateData>
The data have been updated.
<dtml-comment>
This comment is used to disable logging.
The following call records that updates were made
</dtml-comment>
<dtml-call logUpdates>
</dtml-comment>
The dtml-return tag is used to return data rather than text from a DTML method. It provides a way to use DTML methods to perform simple computation that can be used by other DTML methods and Zope objects. The only attributes supported by the dtml-return tag are the standard name and expr attributes.
Consider the following example:
When this DTL method is executed, the number 1 is returned. The text "blah blah" is not returned. In:
If there are any object ids, then the first one is returned, otherwise, the DTML text, "blah" is returned.
Zope objects are organized and presented in a hierarchical fashion, so it is only natural that there should be a DTML facility to aid in the hierarchical display of information. This facility is the dtml-tree tag. The dtml-tree tag is similar to the dtml- in tag, in that it is applied to objects that contain other objects. However, in addition to iterating over sub-objects, the dtml-tree tag provides the ability to expand and iterate over sub-objects of sub-objects.
The dtml-tree tag provides many options which allow you quite a bit of control over how the tree is displayed.
Figure 11 shows two tree views of a Zope site with and without a folder expanded. This view is generated with the DTML shown in figure 12.
![]() |
![]() |
<dtml-var standard_html_header> |
This example shows an extremely simple form of the dtml-tree tag. No attributes are used. Although the dtml-tree tag can use the standard name and expr attributes to specify data to be displayed, these attributes may be and usually are omitted. The dtml-tree tag usually uses the current folder as the source of data to be displayed. The text following the dtml-tree tag is inserted for each "branch" of a tree. The attributes that can be used with the dtml-tree tag are summarized in table 21.
By default, the dtml-tree tag displays branches and sub-branches of an object. Branches are normally found by calling a method named tpValues of the object being displayed by the dtml-tree tag. Many Zope objects, including folders, provide tpValues methods. Alternatively, the branches method may be used to specify a different method to call to find branches. For example, to display all sub-objects of a folder, the objectValues method may be used (figure 13).
An object that does not have sub-branches may instead define "leaves" by using the leaves attribute of the dtml-tree tag. The argument to the leaves attribute is a Document object. This is commonly used when browsing database data. Branches are used to provide a hierarchical organization to data and leaves are used to display data within a hierarchical grouping.
The header and footer attributes are similar to the leaves attribute, in that they are used to specify documents to be displayed when a branch is expanded. Unlike the leaves attribute, they are only used when there are sub-branches of an object. The header document is displayed before the display of sub-branches, and the footer is displayed following sub-branches.
The dtml-tree tag sets a number of variables in the DTML namespace as it renders sub-objects. These variables allow sub-objects to tailor their representation to their position within the tree. Perhaps the most useful variable set by the dtml-tree tag is the tree-item-expanded variable. If this variable is true then the tree item knows that it has been expanded. The variables set by the tree tag are summarized in Table 26.
Additionally, the dtml-tree tag responds to several variables set the DTML namespace. You can expand and collapse the entire tree by setting the expand_all and collapse_all variables. Table 27 details the variables which control tree state.
One common application of these variables is to provide links which allow a tree to be expanded and collapsed. Here's an example of how this could be done in DTML:
<a href="<dtml-var URL0>?expand_all=1">Expand tree</a> |
<a href="<dtml-var URL0>?collapse_all=1">Collapse tree</a>
This snippet of DTML provides two links to the current page. One link will cause the current page's tree to expand, the other will cause it to collapse.
The dtml-sendmail tag is used to send an electronic message using the Simple Mail Transport Protocol (SMTP). Unlike other DTML tags, the dtml-sendmail tag does not cause any text to be included in output. Figure 14 shows a DTML document, named SendFeedback , which uses the dtml-sendmail tag to send information collected in a feedback form (figure 15). The dtml-sendmail tag requires numerous pieces of information that are specified by dtml-sendmail tag attributes, shown in Table 28. At minimum, either a Zope MailHost object must be specified, or a SMTP host address must be specified using a smtphost attribute. The recipients, sender, and subject information are required, but they may be provided either as dtml-sendmail tag attributes, or using "header" lines15 at the beginning of the message (figure 14).
The text following the dtml-sendmail tag can and usually does use DTML tags to include data from input forms and Zope objects. In the S endFeedback example in figure 14, the variables support and feedback are supplied from Folder properties and the variables subject and body are supplied from the FeedbackForm Document shown in figure 15.
The dtml-mime tag is used in conjunction with the dtml-sendmail tag to send attachments along with electronic mail messages16. The dtml-mime tag automatically sets the content type of the entire message to multipart/mixed. Thus, a variety of data can be attached to a single message using one or more dtml-boundary tags. Figure 16 uses the dtml-mime tag to attach the file, yearly_report, to an email formed by the dtml-sendmail tag.
The dtml-mime tag and dtml-boundary tags contain several attributes, listed in Table 19, that specify MIME header information for their particular content. Since the opening dtml-mime tag in Figure 16 contains the body of the message, and does not require encoding, encode is set to 7bit.
Notice in Figure 16, there is no space between the opening dtml-mime tag and the TO: header. If a space is present, then the message will not be interpreted as by the receiving mailreader. Also notice, there are no spaces between the dtml-boundary, var or closing dtml-mime tags. I
Zope provides a facility for working with DateTime data. From Python, a DateTime module provides a DateTime class for creating and formatting DateTime data. From DTML, the special variable _ provides a method for constructing date-time values from strings and numeric data. DateTime objects provide methods that can be used to format data in various ways.
1. It is also possible to define additional syntaxes, although the mechanism for doing this is not currently documented. For example, a syntax that is similar to the syntax used by active server pages has been developed.
2. Actually, all attributes have values. Certain attributes, like the capitalize attribute, have default values which are set when a value is not provided within the tag. The only case in which a value must be provided for this type of attribute is when the attribute is the first attribute in the tag. Without a value, the attribute would be confused with a name attribute value. For attributes like capitalize, a value of "yes", "on" or 1 is usually provided, as in: <dtml-var capitalize=1 name=id>. The capitalize attribute is an example of a flag. The presence of a flag typically indicates that some normally disabled option should be enabled, thus the values of "yes", "on" or 1.
3. In this context, "function" refers any "callable" object. Examples of an callable objects include Zope Database Methods and Zope Network Clients, DTML Methods.
4. For a detailed description of Python syntax, see the Python documentation at http://www.python.org/doc/.
5. A method is like a function except, a method is an attribute of an object and can use the object's data in computation.
6. Zope defines a large number of attributes that are used by Zope itself. Many of these will become part of an official Zope applications programming interface and will be documented in a forthcoming "Zope API Guide".
8.
Dictionaries are objects that support looking of data by name
(e.g.
REQUEST.cookies['CUST_ID']
to look up a cookie named
CUST_ID
). Dictionaries have
has_key
methods for checking whether a dictionary contains a value (e.g.
REQUEST.cookies.has_key('CUST_ID')
) and methods
keys
,
values
, and
items
, for updating lists of dictionary keys, values, and key-value pairs
(e.g.
REQUEST.cookies.keys()
to obtain a list of cookie names).
10. Python 1.4 users must use the ni module to enable packages. DocumentTemplate may also be used as a collection of modules, rather than as a package by copying all of the DocumentTemplate modules except the __init__ module to a directory in the Python path.
12. All Zope objects are either true or false. Numeric values are true if they are non-zero and false if they are zero. Objects that are sequences of objects, like search results, are true if the sequences are non-empty and false otherwise. Most other objects are true.
13. nnn is the name of an attribute or key. For example, to get the mean salary in a collection of employees, each with the attribute salary, mean-salary would be used.
15. A header line is a line that begins with a header name, followed by a colon, a space, and a value. Header lines may have continuation lines that begin with one or more spaces or tabs. All of the header lines, with continuation lines, if any, must start at the beginning of the text following the dtml-sendmail tag and must be separated from the message body by at least one blank line.