Sophie

Sophie

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

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

<html>
<head>
<title>Chapter 6: Creating Basic Zope Applications</title>
</head>
<body bgcolor="#FFFFFF">
<h1>Chapter 6: Creating Basic Zope Applications</h1>
<p>  In Chapter 3, "Using Basic Zope Objects" and Chapter 4, "Dynamic
  Content with DTML" you learned about basic Zope objects and DTML. In
  this chapter you'll see how you can build simple but powerful web
  applications using these tools. In later chapters of the book you'll
  discover more complex objects and more complex DTML. However, the
  design techniques covered in this chapter are still relevant.</p><p>  <em>Note: in chapter 3, "Basic Zope Objects", we explained how Zope
  Page Templates are new to Zope and should be used for presentation.
  We have not yet converted this chapter over to use Page Templates
  instead of DTML.  We will be rewriting this chapter soon to reflect
  new methedologies based on page templates soon.</em></p><h2>  Building Applications with Folders</h2>
<p>    Folders are the "basic building blocks" of Zope applications.
    Folders allow you to organize your Zope objects, and actively
    participate in your web applications. Folders are given behavior
    by adding scripts to them.</p><p>    Scripts and folders work together to build simple applications.
    Folders provide structure for your information and also provide a
    framework for your site's behavior.  Later in this chapter, an
    example of a simple guest book application based on this design
    concept is given.  A folder is used to hold the methods, scripts
    and data of the guest book application, the scripts provide
    behavior that define how the application works, and the methods
    provide presentation to the application.</p><p>    For example, suppose you have an <em>Invoices</em> folder to hold
    invoices. You could create objects inside that folder named
    <em>addInvoice</em> and <em>editInvoice</em> to allow you to add and edit invoices.
    Now your <em>Invoices</em> folder becomes a small application.</p><p>    Zope's simple and expressive URLs are used to work with the invoices
    application. As you've seen, you can display a Zope object by going to
    its URL in your browser.  So for example, the URL
    <em>http://localhost:8080/Invoices/addInvoice</em> calls the <em>addInvoice</em>
    object on the <em>Invoices</em> folder. This URL might take you to a screen
    that lets you add an invoice. Likewise, the URL
    <em>http://localhost:8080/Invoices/editInvoice?invoice_number=42</em> calls
    the <em>editInvoice</em> object on the <em>Invoices</em> folder and passes it the
    argument <em>invoice_number</em> with a value of 42. This URL could allow you
    to edit invoice number 42.</p><h3>    Calling Objects on Folders with URLs    </h3>
<p>      The invoices example demonstrates a powerful Zope feature. You
      can call an object on a folder by going to a URL that consists
      of the folder's URL followed by the id of the object. This
      facility is used throughout Zope and is a very general design
      pattern. In fact you are not just restricted to calling objects
      on folders. You'll see later how you can call objects on all
      kinds of Zope objects using the same URL technique.</p><p>      For example suppose you want to call an object named
      <em>viewFolder</em> on one of your folders. Perhaps you have many
      different <em>viewFolder</em> objects in different locations.  Zope
      figures out which one you want by first looking in the folder
      that you are calling the object on. If it can't find the object
      there it goes up one level and looks in the folder's containing
      folder. If the object can't be found there it goes up another
      level. This process continues until Zope finds the object or
      gets to the root folder. If Zope can't find the object in the
      root it gives up and raises an exception.</p><p>      You'll see this kind of dynamic behavior in many different
      places in Zope. This technique is called <em>acquisition</em>. A folder
      is said to <em>acquire</em> a object by searching for the object in its
      containers.</p><h3>    The Special Folder Object <em>index_html</em></h3>
<p>      As you've seen, folders can acquire all kinds of objects. There is
      one special object that Zope uses to display a folder.  This object
      is named <em>index_html</em>.</p><p>      The <em>index_html</em> object provides a default view of the folder.  This
      is analogous to how an <em>index.html</em> file provides a default view for
      a directory in Apache and other web servers.</p><p>      For example, if you create an <em>index_html</em> object in your
      <em>Invoices</em> folder and view the folder by clicking the View
      tab or by visiting the URL <em>http://localhost:8080/Invoices/</em>, Zope will
      call the <em>index_html</em> object on the <em>Invoices</em> folder.</p><p>      A folder can also acquire an <em>index_html</em> object from its parent
      folders just as it can acquire any object. You can use this behavior
      to create a default view for a bunch of folders all in one place. If
      you want a different default view of a given folder, just create a
      custom <em>index_html</em> object in that folder. This way you can override
      the <em>index_html</em> object defined higher up.</p><h2>  Building the Zope Zoo Website</h2>
<p>    In this section, you'll create a simple web site for the Zope Zoo.  As
    the Zoo webmaster, it is your job to make the web site easy to use and
    manage.  Here are some things you'll need:<ul>
<li>Zoo users must easily move around the site, just as if they
        were walking through a real Zoo.</li>
<li>All of your shared web layout tools, like a Cascading Style
      Sheet (CSS), must be in one easy to manage location.</li>
<li>You must provide a simple file library of various documents
      that describe the animals.</li>
<li>You need a site map so that users can quickly get an idea of
      the layout of the entire Zoo.</li>
<li>A Guest book must be created so that Zoo visitors can give you
        feedback and comments about your site.</li>
<li>A what's new section must be added to the guest book so that you
        can see any recent comments that have been added.</li>
</ul>
</p><h3>    Navigating the Zoo</h3>
<p>      In order for your navigation system to work, your site will need
      some basic structure through which to navigate. Create some
      folders in your Zope system that represent the structure of your
      site.  Let's use a zoo structure with the following layout, as shown in
      <a href="#5-1">Figure 5-1</a>.</p><p>      <a name="5-1"></a>
<img src="Figures/5-1.png" alt="Zoo folder structure.">
<p><b>Figure 5-1</b> Zoo folder structure.</p>
</p><p>      The main structure of the Zope Zoo contains three top level
      folders, <em>Reptiles</em>, <em>Mammals</em> and <em>Fish</em>.  To navigate your site,
      users should first go to your home page and click on one of the
      top level folders to enter that particular part of the Zoo.  They
      should also be able to use a very similar interface to keep going
      deeper into the site; i.e. the snakes section.  Also, the user
      should be able to back out of a section and go up to the parent
      section.</p><p>      You can accomplish this easily with Zope.  In your <em>ZopeZoo</em> folder,
      create a DTML Method called <em>navigation</em>:<pre>        &lt;ul&gt;
        &lt;dtml-in expr=&quot;objectValues('Folder')&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;br&gt;
        &lt;/dtml-in&gt;
        &lt;/ul&gt;</pre>
</p><p>      The method you just created shows a list of links to the various
      sub-sections of the zoo.  It's important to notice that this method can
      work on any zoo folder since it makes no assumptions about the folder.
      Also since we placed this method in the <em>ZopeZoo</em> folder, all the zoo
      folders can acquire it.</p><p>      Now, you need to incorporate this method into the site. Let's put
      a reference to it in the <em>standard_html_header</em> object so that the
      navigation system is available on every page of the site.  Your
      <em>standard_html_header</em> could look like this:<pre>        &lt;html&gt;
        &lt;head&gt;&lt;title&gt;&lt;dtml-var title&gt;&lt;/title&gt;&lt;/head&gt;
        &lt;body&gt;
        &lt;dtml-var navigation&gt;</pre>
</p><p>      Next we need to add a front page to the Zoo site and then we can
      view the site and verify that the navigation works correctly.</p><h3>    Adding a Front Page to the Zoo</h3>
<p>      Now, you need a front page that serves as the welcome screen
      for Zoo visitors.  Let's create a DTML Method in the <em>ZopeZoo</em> folder
      called <em>index_html</em> with the following content:<pre>        &lt;dtml-var standard_html_header&gt;

          &lt;h1&gt;Welcome to the Zope Zoo&lt;/h1&gt;

          &lt;p&gt;Here you will find all kinds of cool animals.  You are in
          the &lt;b&gt;&lt;dtml-var getId&gt;&lt;/b&gt; section.&lt;/p&gt;

        &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>      Take a look at how your site appears by clicking on the
      <em>View</em> tab in the root folder, as shown in <a href="#5-2">Figure 5-2</a>.</p><p>      <a name="5-2"></a>
<img src="Figures/5-2.png" alt="Zope Zoo front page.">
<p><b>Figure 5-2</b> Zope Zoo front page.</p>
</p><p>      Here you start to see how things come together.  At the top of
      your main page you see a list of links to the various
      subsections. These links are created by the <em>navigation</em> method
      that is called by the <em>standard_html_header</em> method.</p><p>      You can use the navigation links to travel through the various sections
      of the Zoo.  Use this navigation interface to find the reptiles
      section.</p><p>      Zope builds this page to display a folder by looking for the default
      folder view method ,<em>index_html</em>. It walks up the zoo site folder by
      folder until it finds the <em>index_html</em> method in the <em>ZopeZoo</em> folder. It
      then calls this method on the <em>Reptiles</em> folder. The <em>index_html</em>
      method calls the <em>standard_html_header</em> method which in turn calls the
      <em>navigation</em> method. Finally, the <em>index_html</em> method displays a welcome
      message and calls the <em>standard_html_footer</em>.</p><p>      What if you want the reptile page to display something besides the
      welcome message? You can replace the <em>index_html</em> method in the reptile
      section with a more appropriate display method and still take
      advantage of the zoo header and footer including navigation.</p><p>      In the <em>Reptile</em> folder create a DTML Method named <em>index_html</em>. Give
      it some content more appropriate to reptiles:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;h1&gt;The Reptile House&lt;/h1&gt;

        &lt;p&gt;Welcome to the Reptile House.&lt;/p&gt;

        &lt;p&gt;We are open from 6pm to midnight Monday through Friday.&lt;/p&gt;

        &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>      Now take a look at the reptile page by going to the <em>Reptile</em> folder
      and clicking the View tab.</p><p>      Since the <em>index_html</em> method in the <em>Reptile</em> folder includes the
      standard headers and footers, the reptile page still includes your
      navigation system.</p><p>      Click on the <em>Snakes</em> link on the reptile page to see what the Snakes
      section looks like. The snakes page looks like the <em>Reptiles</em> page
      because the <em>Snakes</em> folder acquires its <em>index_html</em> display method
      from the <em>Reptiles</em> folder.</p><h3>    Improving Navigation</h3>
<p>      The navigation system for the zoo works pretty well, but it has one big
      problem.  Once you go deeper into the site you need to use your
      browser's <em>back</em> button to go back. There are no navigation links to
      allow you to navigate up the folder hierarchy. Let's add a navigation
      link to allow you to go up the hierarchy. Change the <em>navigation</em>
      method in the root folder:<pre>        &lt;a href=&quot;..&quot;&gt;Return to parent&lt;/a&gt;&lt;br&gt;

        &lt;ul&gt;
        &lt;dtml-in expr=&quot;objectValues('Folder')&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;br&gt;&lt;/li&gt;
        &lt;/dtml-in&gt;
        &lt;/ul&gt;</pre>
</p><p>      Now browse the Zoo site to see how this new link works, as shown
      in Figure <a href="#5-3">Figure 5-3</a>.</p><p>      <a name="5-3"></a>
<img src="Figures/5-3.png" alt="Improved zoo navigation controls.">
<p><b>Figure 5-3</b> Improved zoo navigation controls.</p>
</p><p>      As you can see, the <em>Return to parent</em> link allows you to go
      back up from a section of the site to its parent. However some
      problems remain; when you are at the top level of the site you
      still get a <em>Return to parent</em> link which leads nowhere. Let's
      fix this by changing the <em>navigation</em> method to hide the parent
      link when you're in the <em>ZopeZoo</em> folder:<pre>        &lt;dtml-if expr=&quot;_.len(PARENTS) &gt; 2&quot;&gt;
          &lt;a href=&quot;..&quot;&gt;Return to parent&lt;/a&gt;&lt;br&gt;
        &lt;/dtml-if&gt;

        &lt;ul&gt;
        &lt;dtml-in expr=&quot;objectValues('Folder')&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;br&gt;&lt;/li&gt;
        &lt;/dtml-in&gt;
        &lt;/ul&gt;</pre>
</p><p>      Now the method tests to see if the current object has any parents
      before it display a link to the parent. <em>PARENTS</em> is a list of the
      current object's parents, and <em>len</em> is a utility function which
      returns the length of a list. See Appendix A for more information
      on DTML utility functions. Now view the site. Notice that now
      there is no parent link when you're viewing the main zoo page.</p><p>      There are still some things that could be improved about the
      navigation system. For example, it's pretty hard to tell what
      section of the Zoo you're in. You've changed the reptile section,
      but the rest of the site all looks pretty much the same with the
      exception of having different navigation links. It would be nice
      to have each page tell you what part of the Zoo you're in.</p><p>      Let's change the <em>navigation</em> method once again to display where
      you are:<pre>        &lt;dtml-if expr=&quot;_.len(PARENTS) &gt; 2&quot;&gt;
          &lt;h2&gt;&lt;dtml-var title_or_id&gt; Section&lt;/h2&gt;
          &lt;a href=&quot;..&quot;&gt;Return to parent&lt;/a&gt;&lt;br&gt;
        &lt;/dtml-if&gt;

        &lt;ul&gt;
        &lt;dtml-in expr=&quot;objectValues('Folder')&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;br&gt;&lt;/li&gt;
        &lt;/dtml-in&gt;
        &lt;/ul&gt;</pre>
</p><p>      Now view the site again.</p><p>      <a name="5-4"></a>
<img src="Figures/5-4.png" alt="Zoo page with section information.">
<p><b>Figure 5-4</b> Zoo page with section information.</p>
</p><p>      As you can see in <a href="#5-4">Figure 5-4</a>, the navigation method now tells you what section
      you're in along with links to go to different sections of the zoo.</p><h3>    Factoring out Style Sheets</h3>
<p>      Zoo pages are built by collections of methods that operate on folders.
      For example, the header method calls the navigation method to display
      navigation links on all pages.  In addition to factoring out shared
      behavior such as navigation controls, you can use different Zope
      objects to factor out shared content.</p><p>      Suppose you'd like to use CSS (<a href="http://www.w3.org/Style/CSS/">Cascading Style
      Sheets</a> ) to tailor the look and feel of
      the zoo site. One way to do this would be to include the CSS tags in
      the <em>standard_html_header</em> method. This way every page of the site
      would have the CSS information.  This is a good way to reuse content,
      however, this is not a flexible solution since you may want a different
      look and feel in different parts of your site. Suppose you want the
      background of the snakes page to be green, while the rest of the site
      should have a white background. You'd have to override the
      <em>standard_html_header</em> in the <em>Snakes</em> folder and make it exactly the
      same as the normal header with the exception of the style
      information. This is an inflexible solution since you can't vary the
      CSS information without changing the entire header.</p><p>      You can create a more flexible way to define CSS information by
      factoring it out into a separate object that the header will
      insert. Create a DTML Document in the <em>ZopeZoo</em> folder named
      <em>style_sheet</em>. Change the contents of the document to include some
      style information:<pre>        &lt;style type=&quot;text/css&quot;&gt;
        h1{
          font-size: 24pt;
          font-family: sans-serif;
        }
        p{
          color: #220000;
        }
        body{
          background: #FFFFDD;
        }
        &lt;/style&gt;</pre>
</p><p>      This is a CSS style sheet that defines how to display <em>h1</em>, <em>p</em>
      and <em>body</em> HTML tags.  Now let's include this content into our web
      site by inserting it into the <em>standard_html_header</em> method:<pre>        &lt;html&gt;
        &lt;head&gt;
        &lt;dtml-var style_sheet&gt;
        &lt;/head&gt;
        &lt;body&gt;
        &lt;dtml-var navigation&gt;</pre>
</p><p>      Now, when you look at documents on your site, all of their paragraphs
      will be dark red, and the headers will be in a sans-serif font.</p><p>      To change the style information in a part of the zoo site, just create
      a new <em>style_sheet</em> document and drop it into a folder. All the pages
      in that folder and its sub-folders will use the new style sheet.</p><h3>    Creating a File Library</h3>
<p>      File libraries are common on web sites since many sites distribute
      files of some sort.  The old fashioned way to create a file
      library is to upload your files, then create a web page that
      contains links to those files.  With Zope you can dynamically
      create links to files. When you upload, change or delete files,
      the file library's links can change automatically.</p><p>      Create a folder in the <em>ZopeZoo</em> folder called <em>Files</em>.  This folder 
      contains all of the file you want to distribute to your web visitors.</p><p>      In the <em>Files</em> folder create some empty file objects with names like
      <em>DogGrooming</em> or <em>HomeScienceExperiments</em>, just to give you some sample
      data to work with. Add some descriptive titles to these files.</p><p>      DTML can help you save time maintaining this library. Create an
      <em>index_html</em> DTML Method in the <em>Files</em> folder to list all the
      files in the library:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;h1&gt;File Library&lt;/h1&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>      Now view the <em>Files</em> folder. You should see a list of links to the
      files in the <em>Files</em> folder as shown in <a href="#5-5">Figure 5-5</a>.</p><p>      <a name="5-5"></a>
<img src="Figures/5-5.png" alt="File library contents page.">
<p><b>Figure 5-5</b> File library contents page.</p>
</p><p>      If you add another file, Zope will dynamically adjust the file
      library page. You may also want to try changing the titles of the
      files, uploading new files, or deleting some of the files.</p><p>      The file library as it stands is functional but Spartan.  The library
      doesn't let you know when a file was created, and it doesn't let you
      sort the files in any way. Let's make the library a little fancier.</p><p>      Most Zope objects have a <em>bobobase_modification_time</em> method that
      returns the time the object was last modified. We can use this
      method in the file library's <em>index_html</em> method:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;h1&gt;File Library&lt;/h1&gt;

        &lt;table&gt;
          &lt;tr&gt;
            &lt;th&gt;File&lt;/th&gt;
            &lt;th&gt;Last Modified&lt;/th&gt;
           &lt;/tr&gt;

        &lt;dtml-in expr=&quot;objectValues('File')&quot;&gt;
          &lt;tr&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;td&gt;&lt;dtml-var bobobase_modification_time fmt=&quot;aCommon&quot;&gt;&lt;/td&gt;
          &lt;/tr&gt;
        &lt;/dtml-in&gt;

        &lt;/table&gt;

        &lt;dtml-var standard_html_footer&gt;  </pre>
</p><p>      The new file library method uses an HTML table to display the
      files and their modification times.</p><p>      Finally let's add the ability to sort this list by file name or by
      modification date. Change the <em>index_html</em> method again:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;h1&gt;File Library&lt;/h1&gt;

        &lt;table&gt;
          &lt;tr&gt;
            &lt;th&gt;&lt;a href=&quot;&amp;dtml-URL0;?sort=name&quot;&gt;File&lt;/a&gt;&lt;/th&gt;
            &lt;th&gt;&lt;a href=&quot;&amp;dtml-URL0;?sort=date&quot;&gt;Last Modified&lt;/a&gt;&lt;/th&gt;
           &lt;/tr&gt;

        &lt;dtml-if expr=&quot;_.has_key('sort') and sort=='date'&quot;&gt;
          &lt;dtml-in expr=&quot;objectValues('File')&quot; 
                   sort=&quot;bobobase_modification_time&quot; reverse&gt;
            &lt;tr&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;td&gt;&lt;dtml-var bobobase_modification_time fmt=&quot;aCommon&quot;&gt;&lt;td&gt;
            &lt;/tr&gt;
          &lt;/dtml-in&gt;
        &lt;dtml-else&gt;      
          &lt;dtml-in expr=&quot;objectValues('File')&quot; sort=&quot;id&quot;&gt;
            &lt;tr&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;td&gt;&lt;dtml-var bobobase_modification_time fmt=&quot;aCommon&quot;&gt;&lt;td&gt;
            &lt;/tr&gt;
          &lt;/dtml-in&gt;
        &lt;/dtml-if&gt;

        &lt;/table&gt;

        &lt;dtml-var standard_html_footer&gt;  </pre>
</p><p>      Now view the file library and click on the <em>File</em> and <em>Last Modified</em>
      links to sort the files. This method works with two sorting loops. One
      uses the <em>in</em> tag to sort on an object's <em>id</em>. The other does a reverse
      sort on an object's <em>bobobase_modification_time</em> method. The
      <em>index_html</em> method decides which loop to use by looking for the
      <em>sort</em> variable. If there is a <em>sort</em> variable and if it has a value of
      <em>date</em> then the files are sorted by modification time. Otherwise the
      files are sorted by id.</p><h3>    Building a Guest Book</h3>
<p>      A guest book is a common and useful web application that allows
      visitors to your site to leave messages.  Figure <a href="#5-6">Figure 5-6</a> shows
      what the guest book you're going to write looks like.</p><p>      <a name="5-6"></a>
<img src="Figures/5-6.png" alt="Zoo guest book.">
<p><b>Figure 5-6</b> Zoo guest book.</p>
</p><p>      Start by creating a folder called <em>GuestBook</em> in the root folder.
      Give this folder the title <code>The Zope Zoo Guest Book</code>.  The
      <em>GuestBook</em> folder will hold the guest book entries and methods to
      view and add entries. The folder will hold everything the guest
      book needs. After the guest book is done you will be able to copy
      and paste it elsewhere in your site to create new guest books.</p><p>      You can use Zope to create a guest book several ways, but for this
      example, you'll use one of the simplest.  The <em>GuestBook</em> folder will
      hold a bunch of DTML Documents, one document for each guest book entry.
      When a new entry is added to the guest book, a new document is created
      in the <em>GuestBook</em> folder.  To delete an unwanted entry, just go into
      the <em>GuestBook</em> folder and delete the unwanted document using the
      management interface.</p><p>      Let's create a method that displays all of the entries.  Call this
      method <em>index_html</em> so that it is the default view of the
      <em>GuestBook</em> folder:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;h2&gt;&lt;dtml-var title_or_id&gt;&lt;/h2&gt;

        &lt;!-- Provide a link to add a new entry, this link goes to the
        addEntryForm method --&gt;

        &lt;p&gt;
          &lt;a href=&quot;addEntryForm&quot;&gt;Sign the guest book&lt;/a&gt;
        &lt;/p&gt;

        &lt;!-- Iterate over each DTML Document in the folder starting with
        the newest documents first. --&gt;

        &lt;dtml-in expr=&quot;objectValues('DTML Document')&quot;
                 sort=&quot;bobobase_modification_time&quot; reverse&gt;

        &lt;!-- Display the date, author and contents of each document --&gt;

          &lt;p&gt;
          &lt;b&gt;On &lt;dtml-var bobobase_modification_time fmt=&quot;aCommon&quot;&gt;, 
             &lt;dtml-var guest_name html_quote null=&quot;Anonymous&quot;&gt; said:&lt;/b&gt;&lt;br&gt;

          &lt;dtml-var sequence-item html_quote newline_to_br&gt;

          &lt;!-- Make sure we use html_quote so the users can't sneak any
          HTML onto our page --&gt;

        &lt;/p&gt;

        &lt;/dtml-in&gt;

        &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>      This method loops over all the documents in the folder and displays
      each one. Notice that this method assumes that each document will have
      a <em>guest_name</em> property. If that property doesn't exist or is empty,
      then Zope will use <em>Anonymous</em> as the guest name. When you create a
      entry document you'll have to make sure to set this property.</p><p>      Next, let's create a form that your site visitors will use to add new
      guest book entries. In the <em>index_html</em> method above we already
      created a link to this form. In your <em>GuestBook</em> folder create a new
      DTML Method named <em>addEntryForm</em>:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;p&gt;Type in your name and your comments and we'll add it to the
        guest book.&lt;/p&gt;

        &lt;form action=&quot;addEntryAction&quot; method=&quot;POST&quot;&gt;
        &lt;p&gt; Your name: 
          &lt;input type=&quot;text&quot; name=&quot;guest_name&quot; value=&quot;Anonymous&quot;&gt;
        &lt;/p&gt;
        &lt;p&gt; Your comments: &lt;br&gt;
          &lt;textarea name=&quot;comments&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;/textarea&gt;
        &lt;/p&gt;

        &lt;p&gt;
          &lt;input type=&quot;submit&quot; value=&quot;Send Comments&quot;&gt;
        &lt;/p&gt;  
        &lt;/form&gt;

        &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>      Now when you click on the <em>Sign Guest Book</em> link on the guest book page
      you'll see a form allowing you to type in your comments.  This form
      collects the user's name and comments and submits this information to a
      method named <em>addEntryAction</em>.</p><p>      Now create an <em>addEntryAction</em> DTML Method in the <em>GuestBook</em> folder to
      handle the form. This form will create a new entry document and return
      a confirmation message:<pre>        &lt;dtml-var standard_html_header&gt;

        &lt;dtml-call expr=&quot;addEntry(guest_name, comments)&quot;&gt;

        &lt;h1&gt;Thanks for signing our guest book!&lt;/h1&gt;

        &lt;p&gt;&lt;a href=&quot;&lt;dtml-var URL1&gt;&quot;&gt;Return&lt;/a&gt;
        to the guest book.&lt;/p&gt;

        &lt;dtml-var standard_html_footer&gt;</pre>
</p><p>      This method creates a new entry by calling the <em>addEntry</em> method
      and returns a message letting the user know that their entry has
      been added.</p><p>      The last remaining piece of the puzzle is to write the script that
      will create a document and sets its contents and properties. We'll do
      this in Python since it is much clearer than doing it in DTML. Create
      a Python-based Script in the <em>GuestBook</em> folder called <em>addEntry</em>
      with parameters <em>guest_name</em> and <em>comments</em>:<pre>        ## Script (Python) &quot;addEntry&quot;
        ##parameters=guest_name, comments
        ##
        &quot;&quot;&quot;
        Create a guest book entry.
        &quot;&quot;&quot;
        # create a unique document id
        id='entry_%d' % len(context.objectIds())

        # create the document
        context.manage_addProduct['OFSP'].manage_addDTMLDocument(id,
                                                 title=&quot;&quot;, file=comments)

        # add a guest_name string property
        doc=getattr(context, id)
        doc.manage_addProperty('guest_name', guest_name, 'string')</pre>
</p><p>      This script uses Zope API calls to create a DTML Document and to
      create a property on that document. This script performs the same
      sort of actions in a script that you could do manually; it creates a
      document, edits it and sets a property.</p><p>      The guest book is now almost finished. To use the simple guest
      book, just visit <em>http://localhost:8080/GuestBook/</em>.</p><p>      One final thing is needed to make the guest book complete. More
      than likely your security policy will not allow anonymous site
      visitors to create documents. However the guest book application
      should be able to be used by anonymous visitors. In Chapter 7,
      User and Security, we'll explore this scenario more fully. The
      solution is to grant special permission to the <em>addEntry</em> method
      to allow it to do its work of creating a document. You can do
      this by setting the <em>Proxy role</em> of the method to
      <em>Manager</em>. This means that when the method runs it will work as
      though it was run by a manager regardless of who is actually
      running the method. To change the proxy roles go to the <em>Proxy</em>
      view of the <em>addEntry</em> method, as shown in <a href="#5-7">Figure 5-7</a>.</p><p>      <a name="5-7"></a>
<img src="Figures/5-7.png" alt="Setting proxy roles for the addEntry method.">
<p><b>Figure 5-7</b> Setting proxy roles for the addEntry method.</p>
</p><p>      Now select <em>Manager</em> from the list of proxy roles and click
      <em>Change</em>.</p><p>      Congratulations, you've just completed a functional web
      application. The guest book is complete and can be copied to
      different sites if you want.</p><h3>    Extending the Guest Book to Generate XML</h3>
<p>      All Zope objects can create XML. It's fairly easy to create XML with
      DTML. XML is just a way of describing information. The power of
      XML is that it lets you easily exchange information across the
      network. Here's a simple way that you could represent your guest book in
      XML:<pre>        &lt;guestbook&gt;
          &lt;entry&gt;
            &lt;comments&gt;My comments&lt;/comments&gt;
          &lt;/entry&gt;
          &lt;entry&gt;
            &lt;comments&gt;I like your web page&lt;/comments&gt;
          &lt;/entry&gt;
          &lt;entry&gt;
            &lt;comments&gt;Please no blink tags&lt;/comments&gt;
          &lt;/entry&gt;
        &lt;/guestbook&gt;</pre>
</p><p>      This XML document may not be that complex but it's easy to
      generate. Create a DTML Method named "entries.xml" in your guest
      book folder with the following contents:<pre>        &lt;guestbook&gt;
          &lt;dtml-in expr=&quot;objectValues('DTML Document')&quot;&gt;
          &lt;entry&gt;
            &lt;comments&gt;&lt;dtml-var document_src html_quote&gt;&lt;/comments&gt;
          &lt;/entry&gt;
          &lt;/dtml-in&gt;
        &lt;/guestbook&gt;</pre>
</p><p>      As you can see, DTML is equally adept at creating XML as it is at
      creating HTML. Simply embed DTML tags among XML tags and you're
      set. The only tricky thing that you may wish to do is to set the
      content-type of the response to <em>text/xml</em>, which can be done with
      this DTML code:<pre>        &lt;dtml-call expr=&quot;RESPONSE.setHeader('content-type', 'text/xml')&quot;&gt;</pre>
</p><p>      The whole point of generating XML is producing data in a format
      that can be understood by other systems. Therefore you will
      probably want to create XML in an existing format understood by
      the systems you want to communicate with.  In the case of the
      guest book a reasonable format may be the RSS (Rich Site Summary) XML
      format. RSS is a format developed by Netscape for its
      <em>my.netscape.com</em> site, which has since gained popularity among
      other web logs and news sites.  The Zope.org web site uses DTML to
      build a dynamic RSS document.</p><p>      Congratulations! You've XML-enabled your guest book in just a
      couple minutes. Pat yourself on the back. If you want extra credit,
      research RSS enough to figure out how to change <em>entries.xml</em> to
      generate RSS.</p><h2>  The Next Step</h2>
<p>    This chapter shows how simple web applications can be made.  Zope
    has many more features in addition to these, but these simple
    examples should get you started on create well managed, complex
    web sites.</p><p>    In the next chapter, we'll see how the Zope security system lets
    Zope work with many different users at the same time and allows
    them to collaborate together on the same projects.</p></body>
</html>