Welcome to the Zope Tutorial

  This tutorial show you the basics of using Zope. You will
  learn how to create and manage Zope resources by building
  a web site devoted to tracking Elvis sightings. Each lesson
  includes working examples in Zope that allow you to learn
  by hands-on experimentation.
  
  The tutorial assumes that you are familiar with basic Internet
  technologies such as <a href="http://www.w3.org/MarkUp/Guide/"
  target="_blank">HTML</a>,
  URLs, and web browsers.
  
  The "Back" and "Next" buttons on the bottom of each tutorial
  page allow you to navigate the tutorial.
  
  If you get lost you can use your browser's back button to
  return to an earlier lesson.
  
  If you want to quit the tutorial close your browser window.
  You can return to the tutorial later by visiting the tutorial
  object you created in the Zope management screen, and viewing
  its "README" document.
  
  <dtml-unless expr="checkInstallation(REQUEST)">
  
  Install Tutorial Examples  
  
    Before you can begin the tutorial you must install the tutorial
    examples.
  
      1. Go to the Zope management screen and choose 'Zope Tutorial' from
      the product add list.
  
      2. Choose an id for the tutorial and click the 'Add' button.
  
      3. Now you should be taken to the tutorial.
      
  </dtml-unless>
  
Lesson 1. "Elvis Lives" Home Page

  <dtml-var "tutorialShowLesson(1, REQUEST)">

  Let's create a home page for "Elvis Lives", an organization that
  tracks Elvis sightings.
  
  First you need to create a [DTML Document]
  for the home page. Zope uses 'DTML Documents' for web pages.
  
    1. Select 'DTML Document' from the product add list.

    2. Type 'home.html' for the document [id].
    
    3. Type 'Elvis Lives' for the document [title].
  
    4. Click 'Add and Edit'.
  
  You should now see a screen
  where you can edit your web page.
  
    1. Change the contents of the document to::
      
      <dtml-var standard_html_header>

      <dtml-var header.gif>

      <p>
      Welcome to <i><dtml-var title></i>,
      your source for information about
      Elvis and Elvis sightings.
      </p>

      <dtml-var standard_html_footer>
      
    2. Click the 'Save Changes' button.
    
  The contents of the document are a mixture of HTML and special
  tags called [DTML].
  
  The [<dtml-var>] tag inserts things into
  web pages. In this page we insert a page header, a page footer,
  an image, and a title with DTML.
  
  Now let's see what our page
  looks like.
  
    1. Click the 'View' tab at the top of the screen.
  
  Congratulations you've created
  a web page with Zope.

  Summary
  
    Zope allows you to create and manage objects through
    the web.

    * Zope uses [DTML Document]s
    for web pages.

    * Create Zope objects by choosing them from the product add list.

    * View Zope objects by clicking the 'View' tab.

    * Insert content in web pages with the
    [<dtml-var>] tag.

  In the next lesson you'll expand
  your web site.

Lesson 2. Going to Graceland

  <dtml-var "tutorialShowLesson(2, REQUEST)">

  Elvis loved his home, Graceland.  Let's link an existing 
  page to our web site with information about Graceland.
  
    1. Click on the 'graceland' [Folder].
    
    2. Inside you should see a number of objects including an
    'index_html' document.
    
  If a [Folder] contains an object named [index_html], that object
  provides the folder's default view. This is just like how an
  'index.html' or a 'default.htm' file works with a conventional
  web server.

  Notice that the location of the 'graceland' folder appears at the
  top of the management screen. This tells you the URL of the
  folder. 
  
  You can navigate between Zope management screens using the location
  links. Go back up to the enclosing folders by clicking their ids in
  the URL.
    
    3. Return to the enclosing folder by clicking the 'lesson2' link
    in the folder's URL.
    
    4. Click on the 'home.html' document to edit it.
    
    5. Change the contents of the 'home.html' document to::
    
      <dtml-var standard_html_header>

      <dtml-var header.gif>

      <p>
      Welcome to <i><dtml-var title></i>,
      your source for information about
      Elvis and Elvis sightings.
      </p>
      
      <h2>About Elvis</h2>
      
      <p>
      Elvis was born in
      <a href="graceland">Graceland</a>.
      </p>

      <dtml-var standard_html_footer>
      
    6. Click the 'Save Changes' button.
  
  This adds a link the the 'graceland' folder. Now let's test
  out the link.
  
    7. Click the 'View' tab.
  
  You've successfully created a multi-page site with a link between two
  Zope objects.

  Summary
    
    Zope files and documents have a lot in common with
    conventional web pages--they have names, are arranged in hierarchies,
    and have URLs that correspond to their locations.
    
    * [Folder]s contain other Zope objects.

    * The default object for a Folder is named [index_html].

    * The Zope management screens allow you to navigate between folders
      and determine the URLs of objects.

  In the next lesson you'll learn about moving
  pages around in Zope.

Lesson 3. Elvis's Favorite Foods

  <dtml-var "tutorialShowLesson(3, REQUEST)">

  Elvis really liked to eat. Right now we have a couple pages about
  foods Elvis liked. But as our web site grows we'll need a whole area
  devoted to food. Let's create a [Folder] for food information.
  
    1. Select 'Folder' from the product add list.
    
    2. Type 'food' for the folder id.
    
    3. Type 'Elvis and Food' for the folder title.
    
    4. Click the 'Add' button.
    
  Now we've got some place to put our food related resources. Let's
  move some objects into this folder.
  
    1. Select the 'sandwiches', 'pie', and 'meatloaf' documents by
    clicking their check boxes.
    
    2. Click the 'Cut' button.

    3. Click the 'food' folder to enter it.
    
    4. Click the 'Paste' button.
    
  Now that we've moved some objects, we need to update the links to
  them because an object's URL is related to its location.
  
    1. Return the the 'home.html' document in the 'lesson3' folder,
    by clicking on the 'lesson3' location link and then clicking 
    on the 'home.html' document.
    
    2. Change the links to the sandwiches, pie and cake documents
    to::
    
      <p>
      Elvis liked to eat
      <a href="food/sandwiches">sandwiches</a>,
      <a href="food/pie">pie</a>, and 
      <a href="food/meatloaf">meatloaf</a>.
      </p>
      
    3. Click the 'Save Changes' button.
    
    4. Click the 'View' tab at the top of the screen.
  
  Notice that the food resources are now correctly linked from the home
  page in their new location.
  
  Congratulations you've performed your first
  web site overhaul! 

  Summary

    You can organize Zope object in folders. You can create
    new folders and move objects between folders.

    * Move Zope objects around with [Cut] and [Paste].

    * Folders contain other Zope objects.

    * Moving a Zope object between folders changes its URL. 

  In the next lesson you'll learn how to change
  the look and feel of your site.
    
Lesson 4. Site Contact Information

  <dtml-var "tutorialShowLesson(4, REQUEST)">
  
  Part of running an Elvis web site is getting in touch with Elvis
  fans the world over. One way to do this is to provide contact
  information on your site so that visitors can email you. Let's
  create an email link at the bottom of each page on your site that
  lets people send you feedback.
  
    1. Click the 'Properties' tab.
    
    2. Type 'webmaster' in the Name field.
    
    3. Type your email address in the Value field.
    
    4. Click the 'Add' button.
    
  Now you've created a property that defines your email address. Now
  let's put a link to this address in the web page footer.
  
    1. Click the 'Contents' tab to return to the list of items in the
       folder, then click the 'standard_html_footer' [DTML Method] to edit it.
    
    2. Change the contents of the method to::
    
      <hr>
      <a href="mailto:<dtml-var webmaster>?subject=<dtml-var
      title>">Email Webmaster</a>
      </body>
      </html>
   
    3. Click the 'Save Changes' button.

  We've change the standard Zope footer. Now let's verify that this
  change is reflected in our web pages.
    
    1. Navigate to the 'home.html' document in the 'lesson4' folder
    by clicking on the 'lesson4' location link and then clicking 
    on the 'home.html' document.
    
    2. Now click the 'View' tab to view the web site.
    
  Notice that there is now an email link at the bottom of every web
  page. The email link uses the property you defined and includes the
  title of the web page as the email subject.
  
  The email link appears on every page because every page
  includes the 'standard_html_footer' object with the
  [<dtml-var>] tag.
    
  Summary
  
    By consolidating content into components such as a common footer
    you can provide a uniform look and feel for your web site.
  
    * [Properties] contain small pieces of content.
    
    * Use the [<dtml-var>] tag to insert properties into web
    pages.
    
    * [standard_html_footer] is used as the default Zope web page footer.

  In the next lesson you'll see how to organize content
  with a collection of Zope objects.

Lesson 5. Recent Elvis Sightings

  <dtml-var "tutorialShowLesson(5, REQUEST)">
  Elvis sightings happen all the time. You'd like to record them and
  list them on your web site. Let's look at a simple system for
  organizing sightings and displaying them on your web site.
  
    1. Click the 'sightings' web page.
  
    2. Click the 'View' tab to view it.
    
  Notice how the page lists a number of Elvis sightings. Also notice
  that these sightings weren't specifically listed in the contents of
  the web page. Where did they come from?
  
    1. Click the 'sightingsFolder' folder to enter it.
    
    2. Click on the 'Shelbyville' method to examine it.
  
    3. Go back the 'sightingsFolder' folder by clicking the
    'sightingsFolder' location link.
    
    4. Select the 'Shelbyville' method by clicking its check box.
  
    5. Click the 'Delete' button.
    
  You just deleted a Zope object that describes an Elvis sighting.
  Let's see how this affects the 'sightings' web page.
  
    1. Click the 'sightings' web page.
    
    2. Click the 'View' tab to view it.
    
  The Shelbyville sighting is not longer listed. So the list of
  sightings is somehow built from the methods in the 'sightingsFolder'
  folder.
  
  What if you want the Shelbyville sighting back? Since you deleted
  it, you can't just paste it back. You need to [Undo] your action.
  
    1. Click the 'Undo' tab.
    
    2. Select the first transaction (ending with "manage_delObjects")
    by clicking its check box.
    
    3. Click the 'Undo' button.
    
    4. Click the 'sightingsFolder' folder to enter it.
    
  Sure enough the 'Shelbyville' sighting has returned.  
  
  Summary
  
    Multiple Zope objects can be combined to form complex web pages.
  
    * [DTML Method]s contain chunks of content.
  
    * Web pages can insert content from 'DTML Methods'.
  
    * You can recover from mistakes with [Undo].

  In the next lesson you'll learn about
  looping over lists of Zope objects.
  
Lesson 6. Recent Elvis Sightings, cont.  
  
  <dtml-var "tutorialShowLesson(6, REQUEST)">
  So we've seen that the 'sightings' page is built from objects in the
  'sightingsFolder' folder. How does it work?
  
    1. Click the 'sightings' document to edit it.
  
    2. Change the contents of the document to::
    
      <dtml-var standard_html_header>
      <h2><dtml-var title></h2>
      
      <table border="1">
      <dtml-in expr="sightingsFolder.objectValues()">
      <tr><td>
        <dtml-var sequence-item>
      </td></tr>
      </dtml-in>
      </table>
      
      <dtml-var standard_html_footer>
      
    3. Click the 'Save Changes' button.
    
    4. Click the 'View' tab.
    
  Notice how each sighting now has a box drawn around it.
  
  What's going on? The [<dtml-in>] tag iterates over a list of
  objects. The '&lt;dtml-var sequence-item&gt;' tag inserts the
  current object. The 'expr="sightingsFolder.objectValues()"' part of
  the '&lt;dtml-in&gt;' tags tells it how to get a list of objects. It
  calls the 'objectValues' method of the 'sightingsFolder' folder.
  'objectValues' returns all the objects contained by a folder.
  
  Summary
  
    You can programmatically build web pages with groups of objects
    by looping over them and inserting them.
  
    * [<dtml-in>] iterates over a list of objects.
    
    * '&lt;dtml-var sequence-item&gt;' inserts the current object
    when looping over a list of objects.
    
    * You can get the contents of a folder by calling its
    'objectValues' method.

  In the next lesson you'll learn about how to
  manage and display pictures.
    
Lesson 7. Elvis Photo Archive

  <dtml-var "tutorialShowLesson(7, REQUEST)">
  The King had many faces. We can offer our site visitors a peek at
  the many sides of Elvis with a photo archive.
  
    1. Click the 'photos' document.
  
    2. Click the 'View' tab to view it.
  
  This page shows the photos in the archive one after another. It's not
  very fancy.
  
  Let's improve it to organize the photos by title and size.
  The improved photo archive will list
  the photos by title and includes a link each
  picture.
  
    1. Click the 'photos' document to edit it.
    
    2. Change the document contents to::
    
      <dtml-var standard_html_header>
      
      <h2><dtml-var title></h2>

      <dtml-in expr="photoArchive.objectValues()">
      <p>
        <a href="<dtml-var absolute_url>"><dtml-var title></a>
        (<dtml-var getSize> bytes)
      </p>
      </dtml-in>
      
      <dtml-var standard_html_footer>
     
    3. Click the 'Save Changes' button.
    
    4. Click the 'View' tab.
    
  Notice how the photo list now shows a link to each photo along with
  its size.
  
  Summary
  
    [Image]s can display themselves and can also provide useful
    information such as size, title, and URL.
  
    * Get the contents of a Folder with the 'objectValues' method.
  
    * Get the size of an [Image] with the 'getSize' method.
    
    * Get the URL of an object with the 'absolute_url' method.
  
  In the next lesson you'll learn how to create
  pictures with DTML scripting.
  
Lesson 8. Elvis Photo Archive, cont. 

  <dtml-var "tutorialShowLesson(8, REQUEST)">
  Now that we have a working photo archive, let's enhance it to handle
  submissions from site visitors.
  
    1. Click the 'photoForm' document.
    
    2. Click the 'View' tab to view it.
    
    3. Upload a picture (JPG, GIF, PNG or other graphics format supported
    by your browser.)
    
    4. Now return to the 'lesson8' folder in the Zope management screen
    using your browser's back button.
    
    5. Click the 'photoArchive' folder to enter it.
  
  Notice that there is now a new [Image] object in the folder. This
  image was created when you uploaded your photo.
  
  Let's investigate how this works, and add the ability to give our
  uploaded photo a title.
  
    1. Click the 'photoForm' document.
    
    2. Change the contents of the document to::
    
      <dtml-var standard_html_header>
      
      <h2><dtml-var title></h2>
      
      <p>Upload a picture to the Elvis Photo Archive.</p>
      
      <form action="photoAction" method="post"
      enctype="multipart/form-data">
      <p>Title: <input type="text" name="photo_title"></p>
      <p>File: <input type="file" name="file"></p>
      <input type="submit">
      </form>
      
      <dtml-var standard_html_footer>
  
    3. Click the 'Save Changes' button.
    
  This document collects data needed to create an Image. It calls the
  'photoAction' document with that data. The 'photoAction' document
  actually creates the Image. Now let's customize the 'photoAction'
  document to handle the image title.
    
    1. Click the 'photoAction' document to edit it. 
   
    2. Change the contents of the document to::
    
      <dtml-var standard_html_header>
      
      <h2><dtml-var title></h2>
      
      <dtml-call
        expr="photoArchive.manage_addImage(
          id='', file=file, title=photo_title)">
      
      <p>Thanks for your photo submission.</p>
      
      <dtml-var standard_html_footer>
      
  The 'photoAction' document uses the [<dtml-call>] tag to
  perform an action without inserting anything into the web page. It
  calls the 'manage_addImage' method on the 'photoArchive' folder.
  'manage_addImage' is a folder method that creates a new
  Image.
  
  Summary
  
    You can use forms to pass information between Zope objects.
    You can programmatically create new Zope objects.
  
    * Zope documents can be the action of HTML forms.
  
    * The [<dtml-call>] tag performs an action without inserting
    anything into a web page.
  
    * Create new [Image]s in folder with the 'manage_addImage' method. 

  In the next lesson you'll learn about [HTTP Cookies] and
  personalizing your web site.

Lesson 9. Elvis, Up Close and Personal
  
  <dtml-var "tutorialShowLesson(9, REQUEST)">
  People who come to your site want a personal relationship with
  Elvis. You can provide this by tailoring your site to your viewer's
  needs and preferences. Let's add the ability to bring new Elvis
  sightings to the attention of site visitors. This way when a visitor
  comes to your site they'll immediately know which sightings are new
  since they last visited.
  
    1. Click the 'sightings' document to edit it.
    
    2. Click the 'View' tab to view it.
    
  All the sightings should be
  marked as New.
  
    3. Reload the page.
    
  Now none of the sightings should be marked as New. This is because
  you've already seen them.
  
    4. Click the 'sightingsFolder' folder to enter it.
    
    5. Choose 'DTML Method' from the product add list.
    
    6. Type 'Seattle' for the id. Since the title is optional and isn't
    really needed in this case, leave the title field blank.
    
    7. Click the 'Add and Edit' button.
    
    8. Change the contents of the method to::
    
      <p>6/1/2000 -- Seattle</p>
      <p>Elvis spotted spare changing on Broadway.
      He denied being the King.</p>
    
    9. Click the 'Save Changes' button.
    
  Now you've created a new sighting. Let's see if it is marked as new
  by the sightings page.
  
    10. Click the 'sightings' document in the 'lesson9' folder.
    
    11. Click the 'View' tab.
    
  Sure enough our new sighting is marked New.
  
  How does this work? It uses [HTTP Cookies]. When you visit the
  'sightings' page a cookie is set that records the current time. Then
  each time you return to the page sightings that are newer than the
  cookie will be marked as new.
  
  Let's look at the DTML for the 'sightings' page to see how this is
  done.
  
    1. Click the 'sightings' document to view its contents.
    
  The document sets a cookie with this code::
  
    <dtml-call expr="RESPONSE.setCookie('lastVisited',
      _.DateTime())">
 
  The document checks each sighting when displaying it to see if it is
  newer than the 'lastVisited' cookie::
  
    <dtml-if expr="bobobase_modification_time() >
      _.DateTime(lastVisited)">
  
  Summary
  
    You can use cookies to personalize a web page. Zope documents
    can dynamically control their presentation.
  
    * You can set cookies with the 'RESPONSE.setCookie' method.
    
    * The [<dtml-if>] tag allows you to test conditions.
    
    * The [DateTime] function allows you to get the current time.

    * The 'bobobase_modification_time' method returns the last
    modification time of an object.
 
  In the next lesson you'll learn how to create
  a mail feedback form.
 
Lesson 10. So You've Seen Elvis

  <dtml-var "tutorialShowLesson(10, REQUEST)">
  What's the first thing you do when you spot Elvis? Report it at the
  "Elvis Lives" web site! Let's enhance our site to allow visitors to
  report their Elvis sightings.
  
    1. Click the 'mailhost' [Mail Host] object to edit it.
    
    2. Type the name of your mail server in the 'SMTP Host' field.
    
  Your mail server is typically named 'mail'. For example,
  'mail.elvislives.com'. If you don't know the name of your mail
  server, ask your system administrator, or check the configuration of
  your mail client.
  
    3. Click the 'Save Changes' button.
    
  Now Zope can send mail. Next let's edit the template for the Elvis
  sighting report mail message.
  
    1. Click the 'reportAction' document to edit it.
    
  This document is called when a site visitor fills out an Elvis
  sighting form. This document sends you mail telling you about the
  sighting. Mail is sent with the [<dtml-sendmail>] tag which
  works with the mail host you just configured.
  
  Notice that the 'to' and the 'from' line both reference a
  property named 'send_to'.
 
    2. Click the 'Properties' tab to edit properties.
    
    3. Type your email address into the 'send_to' property field.
    
    4. Click the 'Save Changes' button.
    
    5. Now go to the 'reportForm' document in the 'lesson10' folder.
    
    6. Click the 'View' tab to view it.
    
    7. Fill out the Elvis sighting form and submit it.
    
  You should now receive a piece of email describing the Elvis
  sighting.
  
  Congratulations, you've built a mail form. If you receive
  a Zope error, there is a good chance that you haven't set the 'SMTP
  Host' setting on your mail host object correctly. 
 
  Summary
  
    After you create a mail host, you can send mail from any
    Zope document using the [<dtml-sendmail>] tag.
  
    * [Mail Host]s allow you to send email.
    
    * The [<dtml-sendmail>] tag sends an email message.

  In the next lesson you'll learn how to use Zope
  to put a database on the web.

Lesson 11. The Elvis Files

  <dtml-var "tutorialShowLesson(11, REQUEST)">
  Everyone knows that serious web sites use databases. We agree. Let's
  convert our Elvis sightings system to use a relational database.
  This will provide us with scalability and interoperability.
  
  Let's see how Zope gets data
  from a database.
  
    1. Click the 'connection' [Database Connection] to edit it.
    
  A [Database Connection] tells Zope how to access a relational
  database. 
  
    2. Click the 'Browse' tab to examine the database tables.
    
    3. Click the plus box next to the 'ELVIS_SIGHTINGS' table to
    expand it.
    
  Now you can see the column names and types for this table. Now let's
  see how to get information out of this table.

    1. Click the 'getSightings' [ZSQL Method] in the 'lesson11' folder
    to edit it.
 
  Notice that the SQL statement used to fetch information about Elvis
  sightings is editable in the 'Query template' field.
  
    2. Click the 'Test' tab.
    
    3. Click the 'Submit  Query' button.
    
  This shows you what data the ZSQL Method returns.
  
  A [ZSQL Method] is used to get information out of or into a relational
  database.
  
  Now let's see how to use
  this ZSQL Method in a web page.
  
    1. Click the 'sightings' DTML Document in the 'lesson11' folder
    to edit it. 

  Notice that the sightings are generated by iterating over the
  'sightings' ZSQL Method with the '&lt;dtml-in&gt;' tag.
  
    2. Add a line between each sighting by changing the contents of
    the 'sightings' DTML Document to::
    
      <dtml-var standard_html_header>
      <h2><dtml-var title></h2>

      <dtml-in getSightings>
      <p><dtml-var date> -- <dtml-var location></p>
      <p>Reported by <dtml-var name></p>
      <p><dtml-var description></p>
      <hr>
      </dtml-in>
      
      <dtml-var standard_html_footer>
      
    3. Click the 'Save Changes' button.
    
    4. Click the 'View' tab to view the document.
    
  Summary
  
    Zope can work with data from relational databases in the
    same way it treats other Zope objects.
  
    * [Database Connection]s tell Zope about relational databases.
 
    * [ZSQL Method]s get information out of or into a relational
    database.

Lesson 12. The Elvis Files, cont.

  <dtml-var "tutorialShowLesson(12, REQUEST)"> In the last lesson you
  created an Elvis sightings database. Now let's adapt the this
  database to allow site visitors to submit their own sightings.

  This lesson builds on your experience from the last two lessons. To
  allow folks to report sightings you'll need a report form just like
  you used in lesson 10. 

    1. Click on the 'reportForm' DTML Document to view its contents.

  This document is almost exactly like the report form used in Lesson
  10. It collects data and calls the 'reportAction' document to
  process the data.

    2. Click on the 'reportAction' DTML Document to view its contents.

  This document its simplier than the 'reportAction' document in
  Lesson 10. All it does is 
  thank the user and call the 'insertSighting' ZSQL Method with this
  code::

    <dtml-call insertSighting>

  The real work is done by the 'insertSighting' ZSQL Method. Let's see
  how.

    3. Click on the 'insertSighting' ZSQL Method to view its contents.

  The query template contains the following SQL code::

    insert into elvis_sightings
      values(
    <dtml-sqlvar location type="string">,
    <dtml-sqlvar date type="string">,
    <dtml-sqlvar name type="string">,
    <dtml-sqlvar description type="string"> 
    )
  
  This code inserts a row into the 'elvis_sightings' table. Notice how
  the arguments of this ZSQL Method correspond to the form elements in
  the 'reportSighting' document.

  You can test this SQL code to make sure it
  works correctly.

    1. Click on the 'Test' tab.

    2. Enter some sample data into the automatically generated form.

    3. Click the 'Submit Query' button.

  Zope will send the SQL code to the database and will tell you the
  SQL code that was sent, and the results that the database
  returned. In this case the database will not return anything, since
  the SQL 'INSERT' command produces no results.

  Now return to the 'sightings' document to see if the sample data was
  added to the list of sightings. Play with the system a little bit
  and see how the links between the 'sightings', 'reportForm', and
  'reportAction' documents allow a visitor to navigate the site.

  Summary

    You can easily change data in a relational database with Zope. The
    process for inserting data is very similar to the process for
    querying a database; you use a ZSQL Method in both cases.

    * [ZSQL Method]s can change information in a relational
    database.

    * You can pass arguments to ZSQL Methods from DTML. 

    * Many ZSQL Methods can use the same [Database Connection].

Congratulations

  Well done! You've finished the Zope Tutorial.
  
  You can return to lesson examples and use these objects as the
  basis of your own experiments. Just copy and paste them and start
  changing them.
  
  To find out more about Zope visit
  <a href="http://www.zope.org" target="_blank">Zope.org</a>.
  
  You may be especially interested in the Zope <a
  href="http://www.zope.org/Members/michel/ZB"
  target="_blank">Book</a>, <a
  href="http://www.zope.org/Documentation/How-To"
  target="_blank">How-Tos</a>, <a
  href="http://www.zope.org/Resources/MailingLists"
  target="_blank">mailing lists</a>, Guides and the <a
  href="http://zdp.zope.org" target="_blank">Zope Documentation
  Project</a>.
  
  Please <a href="mailto:docs@digicool.com">let us know</a> what you
  liked and disliked about the Zope Tutorial. Telling us what you
  think helps us improve it.
  
