Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 8b32d38f0094104a5fd847636983daa8 > files > 37

zope-doc-2.11.2-11mdv2010.0.i586.rpm

<html>
<head>
<title>Chapter 4: Dynamic Content with DTML</title>
</head>
<body bgcolor="#FFFFFF">
<h1>Chapter 4: Dynamic Content with DTML</h1>
<p>  <em>DTML</em> (Document Template Markup Language) is Zope's tag-based
  presentation and scripting language.  DTML dynamically generates,
  controls, and formats content.  DTML is commonly used to build
  modular and dynamic web interfaces for your web applications.</p><p>  DTML is a server side scripting language, like SSI, PHP, ASP, and JSP.
  This means that DTML commands are executed by Zope at the server, and the
  result of that execution is sent to your web browser. By contrast,
  client-side scripting languages like Javascript are not processed by the
  server, but are rather sent to and executed by your web browser.</p><p>  You can use DTML scripting in two types of Zope objects, <em>DTML Documents</em>
  and <em>DTML Methods</em>.</p><h2>  Who is DTML For?</h2>
<p>    DTML is designed for people familiar with HTML and basic web scripting,
    not for application programmers.  In fact, if you want to do
    programming with Zope you shouldn't use DTML. In Chapter 9, "Advanced Zope
    Scripting", we'll cover advanced programming using Python and Perl.</p><p>    DTML is for presentation and should be managed by web designers.  Zope
    encourages you to keep your presentation and logic separate by
    providing different objects for presentation (DTML), and logic (Python,
    Perl, and others). You will find a host of benefits resulting from keeping
    your presentation in DTML and your logic in other types of Zope objects.
    Some of those benefits include:<ul>
<li>Keeping logic and presentation separate makes it easy to vary
        either component without disrupting the other.</li>
<li>Often you will have different people in charge of maintaining logic
        and presentation. By using different objects for these
        tasks you make it easier for people to collaborate without
        disrupting each other.</li>
<li>It's easier to reuse existing presentation and logic components if
        they are not intermingled.</li>
</ul>
</p><h2>  What is DTML Good for?</h2>
<p>    DTML is good for creating dynamic web interfaces. It supports reusing
    content and layout, formatting heterogeneous data, and separating
    presentation from logic and data.<p>     For example with DTML you can reuse shared web page headers and
     footers:<pre>      &lt;dtml-var standard_html_header&gt;

      &lt;p&gt;Hello world.&lt;/p&gt;

      &lt;dtml-var standard_html_footer&gt;</pre>
</p></p><p>    This web page mixes HTML and DTML together. DTML commands are
    written as tags that begin with <em>dtml-</em>. This example builds a web
    page by inserting a standard header and footer into an HTML
    page.  The resulting HTML page might look something like this:<pre>      &lt;html&gt;
      &lt;body bgcolor=&quot;#FFFFFF&quot;&gt;

      &lt;p&gt;Hello world.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;Last modified 2000/10/16 by AmosL&lt;/p&gt;
      &lt;/body&gt;
      &lt;/html&gt;</pre>
</p><p>    As you can see the standard header defined a white background
    color and the standard footer added a note at the bottom of the
    page telling when the page was last modified and by whom.</p><p>    In addition to reusing content, DTML lets you easily and
    powerfully format all kinds of data. You can use DTML to call
    methods, query databases, introspect Zope objects, process forms,
    and more.</p><p>    For example when you query a database with a SQL Method it
    typically returns a list of results.  Here's how you might use
    DTML to format each result from a database query:<pre>      &lt;ul&gt;
      &lt;dtml-in frogQuery&gt;
        &lt;li&gt;&lt;dtml-var animal_name&gt;&lt;/li&gt;
      &lt;/dtml-in&gt;
      &lt;/ul&gt;</pre>
</p><p>    The DTML <em>in</em> tag iterates over the results of the database query
    and formats each result. Suppose four results are returned by
    <em>frogQuery</em>. Here's what the resulting HTML might look like:<pre>      &lt;ul&gt;
        &lt;li&gt;Fire-bellied toad&lt;/li&gt;
        &lt;li&gt;African clawed frog&lt;/li&gt;
        &lt;li&gt;Lake Nabu reed frog&lt;/li&gt;
        &lt;li&gt;Chilean four-eyed frog&lt;/li&gt;
      &lt;/ul&gt;</pre>
</p><p>    The results of the database query are formatted as an HTML
    bulleted list.</p><p>    Note that you don't have to tell DTML that you are querying a database
    and you don't have to tell it where to find the arguments to call the
    database query. You just tell it what object to call, it will do the
    work of figuring out how to call the object and pass it appropriate
    arguments. If you replace the <em>frogQuery</em> SQL Method with some other
    kind of object, like a Script, a ZCatalog, or even another DTML
    Method, you won't have to change the way you format the results.</p><p>    This ability to format all kinds of data makes DTML a powerful
    presentation tool, and lets you modify your business logic without
    changing your presentation.</p><h2>  When Not to Use DTML</h2>
<p>    DTML is not a general purpose programming language. For example,
    DTML does not allow you to create variables very easily.  While it
    may be possible to implement complex algorithms in DTML, it is
    painful and not recommended.  If you want to implement programming
    logic, use Python or Perl (for more information on these subjects,
    see Chapter 9, "Advanced Zope Scripting").</p><p>    For example, let's suppose you were writing a simple web page for
    a group of math students, and on that page you wanted to
    illustrate a simple calculation.  You would not want to write the
    program that made this calculation in DTML.  It could be <em>done</em> in
    DTML, but it would be difficult to understand.  DTML would be
    perfect for describing the page that this calculation is inserted
    into, but it would be awful to do this calculation in DTML,
    whereas it may be very simple and trivial in Python or Perl.</p><p>    String processing is another area where DTML is not the best
    choice.  If you want to manipulate input from a user in a complex
    way, but using functions that manipulate strings, you are better
    off doing it in Python or Perl, both of which have much more
    powerful string processing abilities than DTML.</p><p>    DTML is one tool among many available in Zope. If you find yourself
    scratching your head trying to figure out some complicated DTML
    construct, there's a good chance that things would work better if
    you broke your DTML script up into a collection of DTML and Python
    or Perl-based Scripts.</p><h2>  DTML Tag Syntax</h2>
<p>    DTML's syntax is similar to HTML.  DTML is a tag based mark-up
    language. In other words DTML uses tags to do its work. Here is a
    simple snippet of DTML:<pre>      &lt;dtml-var standard_html_header&gt;

      &lt;h1&gt;Hello World!&lt;/h1&gt;

      &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>    This DTML code contains two DTML <em>var</em> tags and some HTML.  The
    <em>h1</em> tags are HTML, not DTML.  You typically mix DTML with other
    mark-up languages like HTML. Normally DTML is used to generate
    HTML, but there's nothing keeping you from generating other types
    of text. As you'll see later you can also use DTML to generate
    mail messages and other textual information.</p><p>    DTML contains two kinds of tags, <em>singleton</em> and <em>block</em> tags.
    Singleton tags consist of one tag enclosed by less-than (&lt;) and
    greater-than (&gt;) symbols.  The <em>var</em> tag is an example of a
    singleton tag:<pre>      &lt;dtml-var parrot&gt;</pre>
</p><p>    There's no need to close the <em>var</em> tag.  </p><p>    Block tags consist of two tags, one that opens the block and one that
    closes the block, and content that goes between them:<pre>      &lt;dtml-in mySequence&gt;

        &lt;!-- this is an HTML comment inside the in tag block --&gt;

      &lt;/dtml-in&gt;</pre>
</p><p>    The opening tag starts the block and the closing tag ends it. The
    closing tag has the same name as the opening tag with a slash
    preceding it. This is the same convention that HTML and XML use.</p><h3>    Using DTML Tag Attributes</h3>
<p>      All DTML tags have attributes. An attribute provides information
      about how the tag is supposed to work. Some attributes are
      optional. For example, the <em>var</em> tag inserts the value of a
      variable. It has an optional <em>missing</em> attribute that specifies a
      default value in case the variable can't be found:<pre>        &lt;dtml-var wingspan missing=&quot;unknown wingspan&quot;&gt;</pre>
</p><p>      If the <em>wingspan</em> variable is not found then <code>unknown wingspan</code>
      is inserted instead.</p><p>      Some attributes don't have values. For example, you can convert
      an inserted variable to upper case with the <em>upper</em> attribute:<pre>        &lt;dtml-var exclamation upper&gt;</pre>
</p><p>      Notice that the <em>upper</em> attribute, unlike the <em>missing</em>
      attribute doesn't need a value.</p><p>      Different tags have different attributes. See Appendix A, "DTML
      Reference", for more information on the syntax of different DTML tags.</p><h2>  Inserting Variables with DTML</h2>
<p>    Inserting a variable is the most basic task that you can perform with
    DTML. You already saw how DTML inserts a header and footer into a web
    page with the <em>var</em> tag.  Many DTML tags insert variables, and they all
    do it in a similar way.  Let's look more closely at how Zope inserts
    variables.</p><p>    Suppose you have a folder whose id is <em>Feedbags</em> that has the title
    "Bob's Fancy Feedbags". Inside the folder
    create a DTML Method with an id of <em>pricelist</em>. Then change the
    contents of the DTML Method to the following:<pre>      &lt;dtml-var standard_html_header&gt;

      &lt;h1&gt;Price list for &lt;dtml-var title&gt;&lt;/h1&gt;

      &lt;p&gt;Hemp Bag $2.50&lt;/p&gt;
      &lt;p&gt;Silk Bag $5.00&lt;/p&gt;

      &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>    Now view the DTML Method by clicking the <em>View</em> tab. You should
    see an HTML page whose source looks something like this:<pre>      &lt;html&gt;
      &lt;body&gt;

      &lt;h1&gt;Price list for Bob's Fancy Feedbags&lt;/h1&gt;

      &lt;p&gt;Hemp Bag $2.50&lt;/p&gt;
      &lt;p&gt;Silk Bag $5.00&lt;/p&gt;     

      &lt;/body&gt;
      &lt;/html&gt;</pre>
</p><p>    This is basically what you might expect. Zope inserts a header, a
    footer, and a title into the web page. DTML gets the values for these
    variables from a number of different places. First, the <em>var</em> tag tries
    to find a variable in the current object. Then it looks in the current
    object's containers. Then it looks in the web request (forms and
    cookies). If Zope cannot find a variable then it raises an exception,
    and it stops executing the DTML.</p><p>    Let's follow this DTML code step by step to see where the variables are
    found.  First Zope looks for <em>standard_html_header</em> in the current
    object, which is the <em>pricelist</em> DTML Method. Next, Zope looks for the
    header in the current object's containers. The <em>Feedbags</em> folder
    doesn't have any methods or properties or sub-objects by that name
    either. Next Zope examines the <em>Feedbags</em> folder's container, and so on
    until it gets to the root folder. The root folder does have a
    sub-object named <em>standard_html_header</em>. The header object is a DTML
    Method. So Zope calls the header method and inserts the results.</p><p>    Next Zope looks for the <em>title</em> variable. Here, the search is a little
    shorter. First, it looks in the <em>pricelist</em> DTML Method, which does not
    have a title, so Zope moves on and finds the <em>Feedbags</em> folder's title
    and inserts it.</p><p>    Finally Zope looks for the <em>standard_html_footer</em> variable. It
    has to search all the way up to the root folder to find it, just like
    it looked for <em>standard_html_header</em>.</p><p>    This exercise may seem a bit tedious, but understanding how Zope
    looks up variables is very important. For example, some important
    implications of how Zope looks up variables include how Zope
    objects can get content and behavior from their parents, and how
    content defined in one location can be reused by many objects.</p><h2>  Processing Input from Forms</h2>
<p>    It's easy to do form processing with Zope.  DTML looks for variables to
    insert in a number of locations, including information that comes from
    submitted HTML forms.  You don't need any special objects, DTML
    Documents and DTML Methods will do.</p><p>    Create two DTML Documents, one with the id <em>infoForm</em> and the other
    with the id <em>infoAction</em>. Now edit the contents of the
    documents. Here's the contents of the <em>infoForm</em> document:<pre>      &lt;dtml-var standard_html_header&gt;

      &lt;p&gt;Please send me information on your aardvark adoption
      program.&lt;/p&gt;

      &lt;form action=&quot;infoAction&quot;&gt;
      name: &lt;input type=&quot;text&quot; name=&quot;user_name&quot;&gt;&lt;br&gt;
      email: &lt;input type=&quot;text&quot; name=&quot;email&quot;&gt;&lt;br&gt;
      &lt;input type=&quot;submit&quot;&gt;
      &lt;/form&gt;

      &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>    Now view this document. It is a web form that asks for information and
    sends it to the <em>infoAction</em> document when you submit the form.</p><p>    Now edit the contents of the <em>infoAction</em> document to make it
    process the form:<pre>      &lt;dtml-var standard_html_header&gt;

      &lt;h1&gt;Thanks &lt;dtml-var user_name&gt;&lt;/h1&gt;

      &lt;p&gt;We received your request for information and will send you
      email at &lt;dtml-var email&gt; describing our aardvark adoption
      program as soon as it receives final governmental approval.
      &lt;/p&gt;

      &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>    This document displays a thanks message which includes name
    and email information gathered from the web form.</p><p>    Now go back to the <em>infoForm</em> document, view it, fill out the
    form and submit it. If all goes well you should see a thank you
    message that includes your name and email address.</p><p>    The <em>infoAction</em> document found the form information from the web
    request that happened when you clicked the submit button on the
    <em>infoForm</em>.  As we mentioned in the last section, DTML looks for
    variables in a couple of places, one of which is the web request, so
    there's nothing special you need to do to enable your documents to
    process web forms.</p><p>    Let's perform an experiment. What happens if you try to view the
    <em>infoAction</em> document directly, as opposed to getting to it from
    the <em>infoForm</em> document. Click on the <em>infoAction</em> document and
    then click the View tab, as shown in <a href="#4-1">Figure 4-1</a>.</p><p>    <a name="4-1"></a>
<img src="Figures/4-1.png" alt="DTML error resulting from a failed variable lookup.">
<p><b>Figure 4-1</b> DTML error resulting from a failed variable lookup.</p>
</p><p>    Zope couldn't find the <em>user_name</em> variable since it was not in the
    current object, its containers or the web request. This is an error
    that you're likely to see frequently as you learn Zope. Don't fear, it
    just means that you've tried to insert a variable that Zope can't
    find.  In this example, you need to either insert a variable that Zope
    can find, or use the <code>missing</code> attribute on the var tag as described
    above:<pre>      &lt;h1&gt;Thanks &lt;dtml-var user_name missing=&quot;Anonymous User&quot;&gt;&lt;/h1&gt;</pre>
</p><p>    Understanding where Zope looks for variables will help you figure out
    how to fix this kind of problem.  In this case, you have viewed a
    document that needs to be called from an HTML form like <em>infoForm</em> in
    order to provide variables to be inserted in the output.</p><h2>  Dynamically Acquiring Content</h2>
<p>    Zope looks for DTML variables in the current object's containers if it
    can't find the variable first in the current object. This behavior
    allows your objects to find and use content and behavior defined in
    their parents.  Zope uses the term <em>acquisition</em> to refer to this
    dynamic use of content and behavior.</p><p>    Now that you see how site structure fits into the way names are looked
    up, you can begin to understand that where you place objects you are
    looking for is very important.</p><p>    An example of acquisition that you've already seen is how web
    pages use standard headers and footers. To acquire the standard
    header just ask Zope to insert it with the <em>var</em> tag:<pre>      &lt;dtml-var standard_html_header&gt;</pre>
</p><p>    It doesn't matter where your DTML Method or Document is
    located. Zope will search upwards until it finds the
    <em>standard_html_header</em> that is defined in the root folder.</p><p>    You can take advantage of how Zope looks up variables to
    customize your header in different parts of your site. Just
    create a new <em>standard_html_header</em> in a folder and it will
    override global header for all web pages in your folder and
    below it.</p><p>    Create a folder in the root folder with an id of <em>Green</em>. Enter
    the <em>Green</em> folder and create a DTML Document with an id of
    <em>welcome</em>. Edit the <em>welcome</em> document to have these contents:<pre>      &lt;dtml-var standard_html_header&gt;

      &lt;p&gt;Welcome&lt;/p&gt;

      &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>    Now view the <em>welcome</em> document. It should look like a simple
    web page with the word <em>welcome</em>, as shown in <a href="#4-2">Figure 4-2</a>.</p><p>    <a name="4-2"></a>
<img src="Figures/4-2.png" alt="Welcome document.">
<p><b>Figure 4-2</b> Welcome document.</p>
</p><p>    Now let's customize the header for the <em>Green</em> folder. Create a
    DTML Method in the <em>Green</em> folder with an id of
    <em>standard_html_header</em>. Then edit the contents of the header to
    the following:<pre>      &lt;html&gt;
      &lt;head&gt;
        &lt;style type=&quot;text/css&quot;&gt;
        body {color: #00FF00;}
        p {font-family: sans-serif;}
        &lt;/style&gt;
      &lt;/head&gt;
      &lt;body&gt;</pre>
</p><p>    Notice that this is not a complete web page. This is just a
    fragment of HTML that will be used as a header. This header uses
    <a href="http://www.w3.org/Style/CSS">CSS</a> (Cascading Style Sheets) to
    make some changes to the look and feel of web pages.</p><p>    Now go back to the <em>welcome</em> document and view it again, as shown in
    <a href="#4-3">Figure 4-3</a>.</p><p>    <a name="4-3"></a>
<img src="Figures/4-3.png" alt="Welcome document with custom header.">
<p><b>Figure 4-3</b> Welcome document with custom header.</p>
</p><p>    The document now looks quite different. This is because it is
    now using the new header we introduced in the <em>Green</em>
    folder. This header will be used by all web pages in the <em>Green</em>
    folder and its sub-folders.</p><p>    You can continue this process of overriding default content by
    creating another folder inside the <em>Green</em> folder and creating a
    <em>standard_html_header</em> DTML Method there. Now web pages in the
    sub-folder will use their local header rather than the <em>Green</em>
    folder's header. Using this pattern you can quickly change the
    look and feel of different parts of your web site. If you later
    decide that an area of the site needs a different header, just
    create one. You don't have to change the DTML in any of the web
    pages; they'll automatically find the closest header and use it.</p><h2>  Using Python Expressions from DTML</h2>
<p>    So far we've looked at simple DTML tags. Here's an example:<pre>      &lt;dtml-var getHippo&gt;</pre>
</p><p>    This will insert the value of the variable named <em>getHippo</em>, whatever
    that may be.  DTML will automatically take care of the details, like
    finding the variable and calling it. We call this basic tag syntax
    <em>name</em> syntax to differentiate it from <em>expression</em> syntax.</p><p>    DTML expressions allow you to be more explicit about how to find and
    call variables. Expressions are tag attributes that contain snippets of
    code in the Python language. For example, instead of letting DTML find
    and call <em>getHippo</em>, we can use an expression to explicitly pass
    arguments:<pre>      &lt;dtml-var expr=&quot;getHippo('with a large net')&quot;&gt;</pre>
</p><p>    Here we've used a Python expression to explicitly call the <em>getHippo</em>
    method with the string argument, <code>with a large net</code>. To find out more
    about Python's syntax, see the <a href="http://www.python.org/doc/current/tut">Python
    Tutorial</a> at the Python.org web
    site.  Many DTML tags can use expression attributes.</p><p>    Expressions make DTML pretty powerful. For example, using Python
    expressions, you can easily test conditions:<pre>        &lt;dtml-if expr=&quot;foo &lt; bar&quot;&gt;
          Foo is less than bar.
        &lt;/dtml-if&gt;</pre>
</p><p>    Without expressions, this very simple task would have to be broken
    out into a separate method and would add a lot of overhead for
    something this trivial.</p><p>    Before you get carried away with expressions, take
    care. Expressions can make your DTML hard to understand. Code that
    is hard to understand is more likely to contain errors and is
    harder to maintain. Expressions can also lead to mixing logic in
    your presentation. If you find yourself staring blankly at an
    expression for more than five seconds, stop. Rewrite the DTML
    without the expression and use a Script to do your
    logic. Just because you can do complex things with DTML doesn't
    mean you should.</p><h3>    DTML Expression Gotchas</h3>
<p>      Using Python expressions can be tricky. One common mistake is
      to confuse expressions with basic tag syntax. For example:<pre>        &lt;dtml-var objectValues&gt;</pre>
</p><p>      and:<pre>        &lt;dtml-var expr=&quot;objectValues&quot;&gt;</pre>
</p><p>      will end up giving you two completely different results. The
      first example of the DTML <em>var</em> tag will automatically render
      variables. In other words it will try to do the right thing to
      insert your variable, no matter what that variable may be. In
      general this means that if the variable is a method it will be
      called with appropriate arguments. This process is covered more
      thoroughly in Chapter 8, "Variables and Advanced DTML".</p><p>      In an expression, you have complete control over the variable
      rendering.  In the case of our example, <em>objectValues</em> is a
      method.  So:<pre>        &lt;dtml-var objectValues&gt;</pre>
</p><p>      will call the method. But:<pre>        &lt;dtml-var expr=&quot;objectValues&quot;&gt;</pre>
</p><p>      will <em>not</em> call the method, it will just try to insert it. The
      result will be not a list of objects but a string such as
      <code>&lt;Python Method object at 8681298&gt;</code>. If you ever see results
      like this, there is a good chance that you're returning a
      method, rather than calling it.</p><p>      To call a method from an expression, you must use standard
      Python calling syntax by using parenthesis:<pre>        &lt;dtml-var expr=&quot;objectValues()&quot;&gt;</pre>
</p><p>      The lesson is that if you use Python expressions you must know
      what kind of variable you are inserting and must use the proper
      Python syntax to appropriately render the variable.</p><p>      Before we leave the subject of variable expressions we should
      mention that there is a deprecated form of the expression
      syntax. You can leave out the "expr=" part on a variable
      expression tag.  But <em>please</em> don't do this.  It is far too easy
      to confuse:<pre>        &lt;dtml-var aName&gt;</pre>
</p><p>      with:<pre>        &lt;dtml-var &quot;aName&quot;&gt;</pre>
</p><p>      and get two completely different results.  These "shortcuts" were
      built into DTML long ago, but we do not encourage you to use them now
      unless you are prepared to accept the confusion and debugging
      problems that come from this subtle difference in syntax.</p><h2>  The <em>Var</em> Tag</h2>
<p>    The <em>var</em> tag inserts variables into DTML Methods and Documents.  We've
    already seen many examples of how the <em>var</em> tag can be used to insert
    strings into web pages.</p><p>    As you've seen, the <em>var</em> tag looks up variables first in the
    current object, then in its containers and finally in the web
    request.</p><p>    The <em>var</em> tag can also use Python expressions to provide more
    control in locating and calling variables.</p><h3>    <em>Var</em> Tag Attributes</h3>
<p>      You can control the behavior of the <em>var</em> tag using its
      attributes. The <em>var</em> tag has many attributes that help you in
      common formatting situations. The attributes are summarized in
      Appendix A. Here's a sampling of <em>var</em> tag attributes.<dl>
<dt>        html_quote</dt>
<dd>This attribute causes the inserted values to be
        HTML quoted.  This means that <code>&lt;</code>, <code>&gt;</code> and <code>&amp;</code> are escaped.</dd>
<dt>        missing</dt>
<dd>The missing attribute allows you to specify a
        default value to use in case Zope can't find the variable. For
        example:<pre>            &lt;dtml-var bananas missing=&quot;We have no bananas&quot;&gt;</pre>
</dd>
<dt>        fmt</dt>
<dd>The fmt attribute allows you to control the format of
        the <em>var</em> tags output. There are many possible formats which are
        detailed in Appendix A.<p>          One use of the <em>fmt</em> attribute is to format monetary
          values. For example, create a <em>float</em> property in your root
          folder called <em>adult_rate</em>.  This property will represent
          the cost for one adult to visit the Zoo.  Give this property
          the value <code>2.2</code>.</p><p>          You can display this cost in a DTML Document or Method like so:<pre>            One Adult pass: &lt;dtml-var adult_rate fmt=dollars-and-cents&gt;</pre>
</p><p>          This will correctly print "$2.20". It will round more
          precise decimal numbers to the nearest penny.</p></dd>
</dl>
</p><h3>    <em>Var</em> Tag Entity Syntax</h3>
<p>      Zope provides a shortcut DTML syntax just for the simple <em>var</em>
      tag.  Because the <em>var</em> tag is a singleton, it can be represented
      with an <em>HTML entity</em> like syntax:<pre>        &amp;dtml-cockatiel;</pre>
</p><p>      This is equivalent to:<pre>        &lt;dtml-var name=&quot;cockatiel&quot; html_quote&gt;</pre>
</p><p>      The main reason to use the entity syntax is to avoid putting
      DTML tags inside HTML tags. For example, instead of writing:<pre>        &lt;input type=&quot;text&quot; value=&quot;&lt;dtml-var name=&quot;defaultValue&quot;&gt;&quot;&gt;</pre>
</p><p>      You can use the entity syntax to make things more readable for
      you and your text editor:<pre>        &lt;input type=&quot;text&quot; value=&quot;&amp;dtml-defaultValue;&quot;&gt;</pre>
</p><p>      The <em>var</em> tag entity syntax is very limited. You can't use
      Python expressions and some tag attributes with it. See Appendix
      A for more information on <em>var</em> tag entity syntax.</p><h2>  The <em>If</em> Tag</h2>
<p>    One of DTML's important benefits is to let you customize your web
    pages. Often customization means testing conditions are responding
    appropriately.  This <em>if</em> tag lets you evaluate a condition and
    carry out different actions based on the result.</p><p>    What is a condition?  A condition is either a true or false
    value. In general all objects are considered true unless they are
    0, None, an empty sequence or an empty string.</p><h3>    Here's an example condition:</h3>
<dl>
<dt>      objectValues</dt>
<dd>True if the variable <em>objectValues</em> exists and
      is true. That is to say, when found and rendered <em>objectValues</em>
      is not 0, None, an empty sequence, or an empty string.</dd>
</dl>
<p>    As with the <em>var</em> tag, you can use both name syntax and expression
    syntax. Here are some conditions expressed as DTML expressions.<dl>
<dt>      expr="1"</dt>
<dd>Always true.</dd>
<dt>      expr="rhino"</dt>
<dd>True if the rhino variable is true.</dd>
<dt>      expr="x < 5"</dt>
<dd>True if x is less than 5.</dd>
<dt>      expr="objectValues('File')"</dt>
<dd>True if calling the <em>objectValues</em>
      method with an argument of <em>File</em> returns a true value.  This
      method is explained in more detail in this chapter.</dd>
</dl>
</p><p>    The <em>if</em> tag is a block tag. The block inside the <em>if</em> tag is executed
    if the condition is true.</p><p>    Here's how you might use a variable expression with the <em>if</em> tag to
    test a condition:<pre>      &lt;p&gt;How many monkeys are there?&lt;/p&gt;

      &lt;dtml-if expr=&quot;monkeys &gt; monkey_limit&quot;&gt;
        &lt;p&gt;There are too many monkeys!&lt;/p&gt;
      &lt;/dtml-if&gt;</pre>
</p><p>    In the above example, if the Python expression <code>monkeys &gt; monkey_limit</code>
    is true then you will see the first and the second paragraphs of
    HTML. If the condition is false, you will only see the first.</p><p>    <em>If</em> tags be nested to any depth, for example, you could have:<pre>      &lt;p&gt;Are there too many blue monkeys?&lt;/p&gt;

      &lt;dtml-if &quot;monkeys.color == 'blue'&quot;&gt;
        &lt;dtml-if expr=&quot;monkeys &gt; monkey_limit&quot;&gt;
          &lt;p&gt;There are too many blue monkeys!&lt;/p&gt;
        &lt;/dtml-if&gt;
      &lt;/dtml-if&gt;</pre>
</p><p>    Nested if tags work by evaluating the first condition, and if that
    condition is true, then evaluating the second.  In general, DTML
    <em>if</em> tags work very much like Python <em>if</em> statements..</p><h3>    Name and Expression Syntax Differences</h3>
<p>      The name syntax checks for the <em>existence</em> of a name, as well as
      its value. For example:<pre>        &lt;dtml-if monkey_house&gt;
          &lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a monkey house Mom!&lt;/p&gt;
        &lt;/dtml-if&gt;  </pre>
</p><p>      If the <em>monkey_house</em> variable does not exist, then this condition
      is false. If there is a <em>monkey_house</em> variable but it is false,
      then this condition is also false. The condition is only true is
      there is a <em>monkey_house</em> variable and it is not 0, None, an empty
      sequence or an empty string.</p><p>      The Python expression syntax does not check for variable
      existence. This is because the expression must be valid
      Python. For example:<pre>        &lt;dtml-if expr=&quot;monkey_house&quot;&gt;
          &lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a monkey house, Mom!&lt;/p&gt;
        &lt;/dtml-if&gt;</pre>
</p><p>      This will work as expected as long as <em>monkey_house</em> exists.  If
      the <em>monkey_house</em> variable does not exist, Zope will raise a
      <em>KeyError</em> exception when it tries to find the variable.</p><h3>    <em>Else</em> and <em>Elif</em> Tags</h3>
<p>      The <em>if</em> tag only lets you take an action if a condition is
      true. You may also want to take a different action if the
      condition is false.  This can be done with the DTML <em>else</em> tag.
      The <em>if</em> block can also contain an <em>else</em> singleton tag. For
      example:<pre>        &lt;dtml-if expr=&quot;monkeys &gt; monkey_limit&quot;&gt;
          &lt;p&gt;There are too many monkeys!&lt;/p&gt;
        &lt;dtml-else&gt;
          &lt;p&gt;The monkeys are happy!&lt;/p&gt;
        &lt;/dtml-if&gt;</pre>
</p><p>      The <em>else</em> tag splits the <em>if</em> tag block into two blocks, the first
      is executed if the condition is true, the second is executed if
      the condition is not true.</p><p>      A <em>if</em> tag block can also contain a <em>elif</em> singleton tag. The <em>elif</em>
      tag specifies another condition just like an addition <em>if</em> tag.
      This lets you specify multiple conditions in one block:<pre>        &lt;dtml-if expr=&quot;monkeys &gt; monkey_limit&quot;&gt;
          &lt;p&gt;There are too many monkeys!&lt;/p&gt;
        &lt;dtml-elif expr=&quot;monkeys &lt; minimum_monkeys&quot;&gt;
          &lt;p&gt;There aren't enough monkeys!&lt;/p&gt;
        &lt;dtml-else&gt;
          &lt;p&gt;There are just enough monkeys.&lt;/p&gt;
        &lt;/dtml-if&gt;</pre>
</p><p>      An <em>if</em> tag block can contain any number of <em>elif</em> tags but only
      one <em>else</em> tag. The <em>else</em> tag must always come after the <em>elif</em>
      tags.  <em>Elif</em> tags can test for condition using either the name
      or expression syntax.</p><h2>  Using Cookies with the <em>If</em> Tag</h2>
<p>    Let's look at a more meaty <em>if</em> tag example.  Often when you have
    visitors to your site you want to give them a cookie to identify
    them with some kind of special value.  Cookies are used frequently
    all over the Internet, and when they are used properly they are
    quite useful.</p><p>    Suppose we want to differentiate new visitors from folks who have
    already been to our site. When a user visits the site we can set a
    cookie. Then we can test for the cookie when displaying pages. If
    the user has already been to the site they will have the
    cookie. If they don't have the cookie yet, it means that they're
    new.</p><p>    Suppose we're running a special. First time zoo visitors get in
    for half price. Here's a DTML fragment that tests for a cookie
    using the <em>hasVisitedZoo</em> variable and displays the price
    according to whether a user is new or a repeat visitor:<pre>      &lt;dtml-if hasVisitedZoo&gt;
        &lt;p&gt;Zoo admission &lt;dtml-var adult_rate fmt=&quot;dollars-and-cents&quot;&gt;.&lt;/p&gt;
      &lt;dtml-else&gt;
        &lt;b&gt;Zoo admission for first time visitors
             &lt;dtml-var expr=&quot;adult_rate/2&quot; fmt=&quot;dollars-and-cents&quot;&gt;&lt;/p&gt;
      &lt;/dtml-if&gt;  </pre>
</p><p>    This fragment tests for the <em>hasVisitedZoo</em> variable. If the user
    has visited the zoo before it displays the normal price for
    admission. If the visitor is here for the first time they get in
    for half-price.</p><p>    Just for completeness sake, here's an implementation of the
    <em>hasVisitedZoo</em> method as a Python-based Script:<pre>      ## Script(Python) &quot;hasVisitedZoo&quot;
      ##parameters=REQUEST, RESPONSE
      ##
      &quot;&quot;&quot;
      Returns true if the user has previously visited
      the Zoo. Uses cookies to keep track of zoo visits.
      &quot;&quot;&quot;
      if REQUEST.has_key('zooVisitCookie'):
          return 1
      else:
          RESPONSE.setCookie('zooVisitCookie', '1')
          return 0</pre>
</p><p>    In Chapter 10, "Advanced Zope Scripting" we'll look more closely
    at how to script business logic with Python and Perl.  For now it
    is sufficient to see that the method looks for a cookie and
    returns a true or false value depending on whether the cookie is
    found or not. Notice how Python uses if and else statements just
    like DTML uses if and <em>else</em> tags. DTML's <em>if</em> and <em>else</em> tags are
    based on Python's. In fact Python also has an elif statement, just
    like DTML.</p><h2>  The <em>In</em> Tag</h2>
<p>    The DTML <em>in</em> tag iterates over a sequence of objects, carrying out
    one block of execution for each item in the sequence.  In
    programming, this is often called <em>iteration</em>, or <em>looping</em>.</p><p>    The <em>in</em> tag is a block tag like the <em>if</em> tag.  The content of the <em>in</em>
    tag block is executed once for every iteration in the <em>in</em> tag
    loop. For example:<pre>      &lt;dtml-in todo_list&gt;
        &lt;p&gt;&lt;dtml-var description&gt;&lt;/p&gt;
      &lt;/dtml-in&gt;</pre>
</p><p>    This example loops over a list of objects named <em>todo_list</em>. For
    each item, it inserts an HTML paragraph with a description of
    the to do item.</p><p>    Iteration is very useful in many web tasks.  Consider a site that
    display houses for sale.  Users will search your site for houses
    that match certain criteria.  You will want to format all of those
    results in a consistent way on the page, therefore, you will need
    to iterate over each result one at a time and render a similar
    block of HTML for each result.</p><p>    In a way, the contents of an <em>in</em> tag block is a kind of <em>template</em>
    that is applied once for each item in a sequence.</p><h3>    Iterating over Folder Contents</h3>
<p>      Here's an example of how to iterate over the contents of a
      folder. This DTML will loop over all the files in a folder and
      display a link to each one.  This example shows you how to
      display all the "File" objects in a folder, so in order to run
      this example you will need to upload some files into Zope as
      explained in the previous chapter:<pre>        &lt;dtml-var standard_html_header&gt;
        &lt;ul&gt;
        &lt;dtml-in expr=&quot;objectValues('File')&quot;&gt;
          &lt;li&gt;&lt;a href=&quot;&amp;dtml-absolute_url;&quot;&gt;&lt;dtml-var title_or_id&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;/dtml-in&gt;
        &lt;/ul&gt;
        &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>      This code displayed the following file listing, as shown in <a href="#4-4">Figure 4-4</a>.</p><p>      <a name="4-4"></a>
<img src="Figures/4-4.png" alt="Iterating over a list of files.">
<p><b>Figure 4-4</b> Iterating over a list of files.</p>
</p><p>      Let's look at this DTML example step by step.  First, the <em>var</em> tag is
      used to insert your common header into the document.  Next, to
      indicate that you want the browser to draw an HTML bulleted list, you
      have the <em>ul</em> HTML tag.</p><p>      Then there is the <em>in</em> tag.  The tag has an expression that is
      calling the Zope API method called <em>objectValues</em>.  This method
      returns a sequence of objects in the current folder that match a
      given criteria.  In this case, the objects must be files.  This
      method call will return a list of files in the current folder.</p><p>      The <em>in</em> tag will loop over every item in this sequence.  If there are
      four file objects in the current folder, then the <em>in</em> tag will execute
      the code in its block four times; once for each object in the
      sequence.</p><p>      During each iteration, the <em>in</em> tag looks for variables in the
      current object, first. In Chapter 8, "Variables and Advanced
      DTML" we'll look more closely at how DTML looks up variables.</p><p>      For example, this <em>in</em> tag iterates over a collection of File
      objects and uses the <em>var</em> tag to look up variables in each
      file:<pre>        &lt;dtml-in expr=&quot;objectValues('File')&quot;&gt;
          &lt;li&gt;&lt;a href=&quot;&amp;dtml-absolute_url;&quot;&gt;&lt;dtml-var title_or_id&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;/dtml-in&gt;</pre>
</p><p>      The first <em>var</em> tag is an entity and the second is a normal DTML
      <em>var</em> tag.  When the <em>in</em> tag loops over the first object its
      <em>absolute_url</em> and <em>title_or_id</em> variables will be inserted in
      the first bulleted list item:<pre>        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;http://localhost:8080/FirstFile&quot;&gt;FirstFile&lt;/a&gt;&lt;/li&gt;</pre>
</p><p>      During the second iteration the second object's <em>absolute_url</em>
      and <em>title_or_id</em> variables are inserted in the output:<pre>        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;http://localhost:8080/FirstFile&quot;&gt;FirstFile&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;http://localhost:8080/SecondFile&quot;&gt;SecondFile&lt;/a&gt;&lt;/li&gt;</pre>
</p><p>      This process will continue until the <em>in</em> tag has iterated over
      every file in the current folder.  After the <em>in</em> tag you
      finally close your HTML bulleted list with a closing <em>ul</em> HTML
      tag and the <em>standard_html_footer</em> is inserted to close the
      document.</p><h3>    <em>In</em> Tag Special Variables</h3>
<p>      The <em>in</em> tag provides you with some useful information that
      lets you customize your HTML while you are iterating over a
      sequence.  For example, you can make your file library easier to
      read by putting it in an HTML table and making every other table
      row an alternating color, like this, as shown in <a href="#4-5">Figure 4-5</a>.</p><p>      <a name="4-5"></a>
<img src="Figures/4-5.png" alt="File listing with alternating row colors.">
<p><b>Figure 4-5</b> File listing with alternating row colors.</p>
</p><p>      The <em>in</em> tag makes this easy.  Change your file library method a
      bit to look like this:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;table&gt;
        &lt;dtml-in expr=&quot;objectValues('File')&quot;&gt;
          &lt;dtml-if sequence-even&gt;
            &lt;tr bgcolor=&quot;grey&quot;&gt;
          &lt;dtml-else&gt;
            &lt;tr&gt;
          &lt;/dtml-if&gt;    
          &lt;td&gt;
          &lt;a href=&quot;&amp;dtml-absolute_url;&quot;&gt;&lt;dtml-var title_or_id&gt;&lt;/a&gt;
          &lt;/td&gt;&lt;/tr&gt;
        &lt;/dtml-in&gt;
        &lt;/table&gt;

        &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>    Here an <em>if</em> tag is used to test for a special variable called
    <code>sequence-even</code>.  The <em>in</em> tag sets this variable to a true or false
    value each time through the loop.  If the current iteration number is
    even, then the value is true, if the iteration number is odd, it is
    false.</p><p>    The result of this test is that a <em>tr</em> tag with either a gray
    background or no background is inserted into the document for
    every other object in the sequence.  As you might expect, there is
    a <code>sequence-odd</code> that always has the opposite value of
    <code>sequence-even</code>.</p><p>    There are many special variables that the <em>in</em> tag defines for you.  Here
    are the most common and useful:<dl>
<dt>      sequence-item</dt>
<dd>This special variable is the current item in the
      iteration.<p>        In the case of the file library example, each time through the loop
        the current file of the iteration is assigned to sequence-item.  It
        is often useful to have a reference to the current object in the
        iteration.</p></dd>
<dt>      sequence-index</dt>
<dd>the current number, starting from 0, of iterations
      completed so far.  If this number is even, <code>sequence-even</code> is true and
      <code>sequence-odd</code> is false.</dd>
<dt>      sequence-number</dt>
<dd>The current number, starting from 1, of iterations
      completed so far.  This can be thought of as the cardinal position
      (first, second, third, etc.) of the current object in the loop.
      If this number is even, <code>sequence-even</code> is false and <code>sequence-odd</code>
      is true.</dd>
<dt>      sequence-start</dt>
<dd>This variable is true for the very first iteration.</dd>
<dt>      sequence-end</dt>
<dd>This variable is true for the very last iteration.</dd>
</dl>
</p><p>    These special variables are detailed more thoroughly in Appendix A.</p><p>    DTML is a powerful tool for creating dynamic content. It allows
    you to perform fairly complex calculations. In Chapter 8,
    "Variables and Advanced DTML", you'll find out about many more
    DTML tags, and more powerful ways to use the tags you already have
    seen. Despite its power, you should resist the temptation to use
    DTML for complex scripting. In Chapter 10, "Advanced Zope
    Scripting" you'll find out about how to use Python and Perl for
    scripting business logic.</p></body>
</html>