.. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.. % Copyright 2001 by Object Craft P/L, Melbourne, Australia.
.. % LICENCE - see LICENCE file distributed with this software for details.
.. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


.. _tug-guide:

********************
Templates User Guide
********************

There are many different ways which you can use Albatross to assist in the
construction of a web application.  The purpose of this guide is to slowly
introduce the features of Albatross to allow you to learn which features can be
useful in your application.

All of the example programs in this chapter are distributed with the source in
the ``samples/templates`` directory.


.. _tug-simple1:

Introduction to CGI
===================

This section presents a very simple program which will introduce you to CGI
programming.  This serves two purposes; it will verify that your web server is
configured to run CGI programs, and it will demonstrate how simple CGI
programming can be.

The sample program from this section is supplied in the
``samples/templates/simple1`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/simple1
   python install.py

The ``simple.py`` program is show below.

   .. literalinclude:: ../samples/templates/simple1/simple.py
      :language: python

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/simple1/simple.py>`_.

If after installing the program locally you do not see a page displaying the
text "Hello from my simple CGI application!" then you should look in the web
server error log for clues.  The location of the error log is specified by the
``ErrorLog`` directive in the Apache configuration.  On a Debian Linux system
the default location is ``/var/log/apache/error.log``.  While developing web
applications you will become intimately familiar with this file.

Knowing how Apache treats a request for a document in the ``cgi-bin`` directory
is the key to understanding how CGI programs work.  Instead of sending the
document text back to the browser Apache executes the "document" and sends the
"document" output back to the browser.  This simple mechanism allows you to
write programs which generate HTML dynamically.

If you view the page source from the ``simple1.py`` application in your browser
you will note that the first two lines of output produced by the program are not
present.  This is because they are not part of the document.  The first line is
an HTTP (Hypertext Transfer Protocol) header which tells the browser that the
document content is HTML.  The second line is blank which signals the end of
HTTP headers and the beginning of the document.

You can build quite complex programs by taking the simple approach of embedding
HTML within your application code.  The problem with doing this is that program
development and maintenance becomes a nightmare. The essential implementation
(or business level) logic is lost within a sea of presentation logic.  The
impact of embedding HTML in your application can be reduced somewhat by using a
package called ``HTMLgen``.  [#]_

The other way to make complex web applications manageable is to separate the
presentation layer from the application implementation via a templating system.
This is also the Albatross way.


.. _tug-simple2:

Your First Albatross Program
============================

This section rewrites the sample CGI program from the previous section as an
Albatross program.  The program uses the Albatross templating system to generate
the HTML document.

The sample program from this section is supplied in the
``samples/templates/simple2`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/simple2
   python install.py

All of the HTML is moved into a template file called ``simple.html``.

   .. literalinclude:: ../samples/templates/simple2/simple.html
      :language: albatross

The ``simple.py`` program is then rewritten as shown below.

   .. literalinclude:: ../samples/templates/simple2/simple.py
      :language: python

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/simple2/simple.py>`_.

This is probably the most simple application that you can write using Albatross.
Let's analyse the program step-by-step.

This first line imports the Albatross package and places the
:class:`SimpleContext` into the global namespace.

.. code-block:: python

   from albatross import SimpleContext

Before we can use Albatross templates we must create an execution context which
will be used to load and execute the template file.  The Albatross
:class:`SimpleContext` object should be used in programs which directly load and
execute template files.  The :class:`SimpleContext` constructor has a single
argument which specifies a path to the directory from which template files will
be loaded.  Before Apache executes a CGI program it sets the current directory
to the directory where that program is located.  We have installed the template
file in the same directory as the program, hence the path ``'.'``.

.. code-block:: python

   ctx = SimpleContext('.')

Once we have an execution context we can load template files.  The return value
of the execution context :meth:`load_template` method is a parsed template.

.. code-block:: python

   templ = ctx.load_template('simple.html')

Albatross templates are executed in two stages; the first stage parses the
template and compiles the embedded Python expressions, the second actually
executes the template.

To execute a template we call it's :meth:`to_html` method passing an execution
context.  Albatross tags access application data and logic via the execution
context.  Since the template for the example application does not refer to any
application functionality, we do not need to place anything into the context
before executing the template.

.. code-block:: python

   templ.to_html(ctx)

Template file output is accumulated in the execution context.

Unless you use one of the Albatross application objects you need to output your
own HTTP headers.

.. code-block:: python

   print 'Content-Type: text/html'
   print

Finally, you must explicitly flush the context to force the HTML to be written
to output.  Buffering the output inside the context allows applications to trap
and handle any exception which occurs while executing the template without any
partial output leaking to the browser.

.. code-block:: python

   ctx.flush_content()


.. _tug-simple3:

Introducing Albatross Tags
==========================

In the previous section we presented a simple Albatross program which loaded and
executed a template file to generate HTML dynamically.  In this section we will
place some application data into the Albatross execution context so that the
template file can display it.

To demonstrate how Albatross programs separate application and presentation
logic we will look at a program which displays the CGI program environment.  The
sample program from this section is supplied in the
``samples/templates/simple3`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/simple3
   python install.py

The CGI program ``simple.py`` is shown below.

   .. literalinclude:: ../samples/templates/simple3/simple.py
      :language: python

The following lines construct a sorted list of all defined environment
variables.  It makes the display a little nicer if the values are sorted. ::

   keys = os.environ.keys()
   keys.sort()

The Albatross execution context is constructed with an empty object in the
:attr:`locals` member which is used as a conduit between the application and the
toolkit.  It is used as the local namespace for expressions evaluated in
template files.  To make the environment available to the template file we
simply assign to an attribute using a name of our choosing which can then be
referenced by the template file. ::

   ctx.locals.keys = keys
   ctx.locals.environ = os.environ

The :class:`SimpleContext` constructor save a reference ( in the :attr:`globals`
member) to the global namespace of the execution context to the globals of the
code which called the constructor.

Now the template file ``simple.html``.  Two Albatross tags are used to display
the application data; ``<al-for>`` and ``<al-value>``.

   .. literalinclude:: ../samples/templates/simple3/simple.html
      :language: albatross

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/simple3/simple.py>`_.

The ``<al-for>`` Albatross tag iterates over the list of environment variable
names we placed in the ``keys`` value (``ctx.locals.keys``).

All template file content enclosed by the ``<al-for>`` tag is evaluated for each
value in the sequence returned by evaluating the ``expr`` attribute.  The
``iter`` attribute specifies the name of the iterator which is used to retrieve
each successive value from the sequence.  The toolkit places the iterator object
in the :attr:`locals` member of the execution context.  Be careful that you do
not overwrite application values by using an iterator of the same name as an
application value.

The ``<al-value>`` Albatross tag is used to retrieve values from the execution
context.  The ``expr`` attribute can contain any Python expression which can
legally be passed to the Python ``eval()`` function when the *kind* argument is
``"eval"``.

Deciding where to divide your application between implementation and
presentation can be difficult at times.  In the example above, we implemented
some presentation logic in the program; we sorted the list of environment
variables.  Let's make a modification which removes that presentation logic from
the application.

The ``simple.py`` application is shown below.

   .. literalinclude:: ../samples/templates/simple4/simple.py
      :language: python

Now look at the new ``simple.html`` template file.  By using the Albatross
``<al-exec>`` tag we can prepare a sorted list of environment variable names for
the ``<al-for>`` tag.

   .. literalinclude:: ../samples/templates/simple4/simple.html
      :language: albatross

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/simple4/simple.py>`_.

The ``<al-exec>`` tag compiles the contents of the ``expr`` tag by passing
``"exec"`` as the *kind* argument. This means that you can include quite complex
Python code in the attribute. Remember that we want to minimise the complexity
of the entire application, not just the Python mainline.  If you start placing
application logic in the presentation layer, you will be back to having an
unmaintainable mess.

Just for your information, the ``<al-exec>`` tag could have been written like
this::

      <al-exec expr="
   keys = environ.keys()
   keys.sort()
   ">


.. _tug-naughty:

Eliminating the Application
---------------------------

Let's revisit our first Albatross application with the ``simple.py`` sample
program in the ``samples/templates/simple5`` directory.

   .. literalinclude:: ../samples/templates/simple5/simple.py
      :language: python

Now consider the template file ``simple.html``.

   .. literalinclude:: ../samples/templates/simple5/simple.html
      :language: albatross

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/simple5/simple.py>`_.

You will notice that we have completely removed any application logic from the
Python program.  This is a cute trick for small example programs, but it is
definitely a bad idea for any real application.


.. _tug-content1:

Building a Useful Application
=============================

In the previous section we saw how Albatross tags can be used to remove
presentation logic from your application.  In this section we will see how with
a simple program we can serve up a tree of template files.

If you look at the output of the ``simple4/simple.py`` program you will notice
the following lines:

.. code-block:: none

   REQUEST_URI     /cgi-bin/alsamp/simple4/simple.py
   SCRIPT_FILENAME /usr/lib/cgi-bin/alsamp/simple4/simple.py
   SCRIPT_NAME     /cgi-bin/alsamp/simple4/simple.py

Now watch what happens when you start appending extra path elements to the end
of the URL.  Try requesting the following with your browser:
`<http://www.object-craft.com.au/cgi-bin/alsamp/simple4/simple.py/main.html>`_.

You should see the following three lines:

.. code-block:: none

   REQUEST_URI     /cgi-bin/alsamp/simple4/simple.py/main.html
   SCRIPT_FILENAME /usr/lib/cgi-bin/alsamp/simple4/simple.py
   SCRIPT_NAME     /cgi-bin/alsamp/simple4/simple.py

The interesting thing is that Apache is still using the ``simple4/simple.py``
program to process the browser request.  We can use the value of the
``REQUEST_URI`` environment variable to locate a template file which will be
displayed.

The sample application in the ``samples/templates/content1`` directory
demonstrates serving dynamic content based upon the requested URI.  The program
can be installed in your web server ``cgi-bin`` directory by running the
following commands.

.. code-block:: none

   cd samples/templates/content1
   python install.py

The CGI program ``content.py`` is shown below.

   .. literalinclude:: ../samples/templates/content1/content.py
      :language: python

To demonstrate this application we have three template files; ``main.html``,
``oops.html``, and ``other.html``.

First ``main.html``.

   .. literalinclude:: ../samples/templates/content1/main.html
      :language: albatross

Now ``other.html``.

   .. literalinclude:: ../samples/templates/content1/other.html
      :language: albatross

And finally the page for displaying errors; ``oops.html``.

   .. literalinclude:: ../samples/templates/content1/oops.html
      :language: albatross

Test the program by trying a few requests with your browser:

* `<http://www.object-craft.com.au/cgi-bin/alsamp/content1/content.py>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content1/content.py/main.html>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content1/content.py/other.html>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content1/content.py/error.html>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content1/content.py/oops.html>`_

Let's analyse the program step-by-step.  The preamble imports the modules we are
going to use.

.. code-block:: python

   #!/usr/bin/python
   import os
   from albatross import SimpleContext, TemplateLoadError

The next part of the program removes the prefix in the ``SCRIPT_NAME`` variable
from the value in the ``REQUEST_URI`` variable.  When removing the script name
we add one to the length to ensure that the ``"/"`` path separator between the
script and page is also removed.  This is important because the execution
context :meth:`load_template` method uses ``os.path.join()`` to construct a
script filename by combining the *base_dir* specified in the constructor and the
name passed to the :meth:`load_template` method.  If any of the path components
being joined begin with a ``"/"`` then ``os.path.join()`` creates an absolute
path beginning at the ``"/"``.

If no page was specified in the browser request then we use the default page
``main.html``.

.. code-block:: python

   script_name = os.environ['SCRIPT_NAME']
   request_uri = os.environ['REQUEST_URI']
   page = request_uri[len(script_name) + 1:]
   if not page:
       page = 'main.html'

The next section of code creates the Albatross execution context and places the
requested filename into the ``page`` local attribute. It then attempts to load
the requested file.  If the template file does not exist the
:meth:`load_template` will raise a ``TemplateLoadError`` exception.  We handle
this by loading the error page ``oops.html``.

The error page displays a message which explains that the requested page (saved
in the ``page`` variable) does not exist.

.. code-block:: python

   ctx = SimpleContext('templ')
   ctx.locals.page = page
   try:
       templ = ctx.load_template(page)
   except TemplateLoadError:
       templ = ctx.load_template('oops.html')

Looking at the error page ``oops.html``, you will see a new Albatross tag
``<al-if>``.

.. code-block:: albatross

   <al-if expr="page == 'oops.html'">
    You actually requested the error page!
   <al-else>
    Sorry, the page <font color="red"><al-value expr="page"></font>
    does not exist.
   </al-if>

The ``<al-if>`` tag allows you to conditionally include or exclude template
content by testing the result of an expression. Remember that we placed the name
of the requested page into the ``page`` variable, so we are able to display
different content when the browser actually requests ``oops.html``.

Finally, the remainder of the program displays the selected HTML page.

.. code-block:: python

   templ.to_html(ctx)

   print 'Content-Type: text/html'
   print
   ctx.flush_content()


.. _tug-content2:

Albatross Macros
================

In the previous section we demonstrated a program which can be used to display
pages from a collection of template files.  You might recall that the HTML in
the template files was very repetitive.  In this section you will see how
Albatross macros can be used to introduce a common look to all HTML pages.

If we look at the ``main.html`` template file again you will notice that there
really is very little content which is unique to this page.

   .. literalinclude:: ../samples/templates/content1/main.html
      :language: albatross

Using Albatross macros we can place all of the boilerplate into a macro.  Once
defined, the macro can be reused in all template files.

The sample program from this section is supplied in the
``samples/templates/content2`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/content2
   python install.py

First consider the macro in the ``macros.html`` template file.

   .. literalinclude:: ../samples/templates/content2/macros.html
      :language: albatross

Now we can change ``main.html`` to use the macro.

   .. literalinclude:: ../samples/templates/content2/main.html
      :language: albatross

Likewise, the ``other.html`` file.

   .. literalinclude:: ../samples/templates/content2/other.html
      :language: albatross

And finally the error page ``oops1.html``.

   .. literalinclude:: ../samples/templates/content2/oops.html
      :language: albatross

We also have to modify the application to load the macro definition before
loading the requested pages.

   .. literalinclude:: ../samples/templates/content2/content.py
      :language: python

Test the program by trying a few requests with your browser:

* `<http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/main.html>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/other.html>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/error.html>`_

*
  `<http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/oops.html>`_

The only new line in this program is the following:

.. code-block:: python

   ctx.load_template('macros.html').to_html(ctx)

This loads the file which contains the macro definition and then executes it.
Executing the macro definition registers the macro with the execution context,
it does not produce any output.  This means that once defined the macro is
available to all templates interpreted by the execution context.  The template
is not needed once the macro has been registered so we can discard the template
file.

When you use Albatross application objects the macro definition is registered in
the application object so can be defined once and then used with all execution
contexts.

There is one small problem with the program.  What happens if the browser
requests ``macros.html``?  Suffice to say, you do not get much useful output.
The way to handle this problem is to modify the program to treat requests for
``macros.html`` as an error.

Let's revisit the macro definition in ``macros.html`` and see how it works.
Albatross macros use four tags; ``<al-macro>``, ``<al-usearg>``,
``<al-expand>``, and ``<al-setarg>``.

   .. literalinclude:: ../samples/templates/content2/macros.html
      :language: albatross

The ``<al-macro>`` tag is used to define a named macro.  The ``name`` attribute
uniquely identifies the macro within the execution context.  In our template
file we have defined a macro called ``"doc"``.  All content enclosed in the
``<al-macro>`` tag will be substituted when the macro is expanded via the
``<al-expand>`` tag.

In all but the most simple macros you will want to pass some arguments to the
macro.  The place where the arguments will be expanded is controlled via the
``<al-usearg>`` tag in the macro definition. All macros accept an "unnamed"
argument which captures all of the content within the ``<al-expand>`` tag not
enclosed by ``<al-setarg>`` tags.  The unnamed argument is retrieved within the
macro definition by using ``<al-usearg>`` without specifying a ``name``
attribute.

In our example we used a fairly complex macro.  If you are still a bit confused
the following sections should hopefully clear up that confusion.


.. _tug-zeromacro:

Zero Argument Macros
--------------------

The most simple macro is a macro which does not accept any arguments. You might
define the location of the company logo within a zero argument macro.

.. code-block:: albatross

   <al-macro name="small-logo">
   <img src="http://images.company.com/logo/small.png">
   </al-macro>

Then whenever you need to display the logo all you need to do is expand the
macro.

.. code-block:: albatross

   <al-expand name="small-logo"/>

This allows you to define the location and name of your company logo in one
place.


.. _tug-singlemacro:

Single Argument Macros
----------------------

The single argument macro is almost as simple as the zero argument macro.  You
should always use the unnamed argument to pass content to a single argument
macro.

If you look at news sites such as `<http://slashdot.org/>`_ you will note that
they make heavy use of HTML tricks to improve the presentation of their pages.
Single argument macros can be extremely useful in simplifying your template
files by moving the complicated HTML tricks into a separate macro definition
file.

Let's look at the top story at `<http://slashdot.org/>`_ to illustrate the
point.  The title bar for the story is constructed with the following HTML
(reformatted so it will fit on the page).

.. code-block:: html

   <table width="100%" cellpadding=0 cellspacing=0 border=0>
   <tr>
   <td valign=top bgcolor="#006666">
   <img src="http://images.slashdot.org/slc.gif" width=13 height=16 alt="" align=top>
   <font size=4 color="#FFFFFF" face="arial,helvetica">
   <b>Another Nasty Outlook Virus Strikes</b>
   </font>
   </td>
   </tr>
   </table>

As you can see, most of the HTML is dedicated to achieving a certain effect.  If
you were using Albatross to construct the same HTML you would probably create a
macro called ``story-title`` like this:

.. code-block:: albatross

   <al-macro name="story-title">
   <table width="100%" cellpadding=0 cellspacing=0 border=0>
   <tr>
   <td valign=top bgcolor="#006666">
   <img src="http://images.slashdot.org/slc.gif" width=13 height=16 alt="" align=top>
   <font size=4 color="#FFFFFF" face="arial,helvetica">
   <b><al-usearg></b>
   </font>
   </td>
   </tr>
   </table>
   </al-macro>

Then you could generate the story title HTML like this:

.. code-block:: albatross

   <al-expand name="story-title">Another Nasty Outlook Virus Strikes</al-expand>

Since stories are likely to be generated from some sort of database it is more
likely that you would use something like this:

.. code-block:: albatross

   <al-expand name="story-title"><al-value expr="story.title"></al-expand>


.. _tug-multimacro:

Multiple Argument Macros
------------------------

Multiple argument macros are effectively the same as single argument macros that
accept additional named arguments.

The following example shows a macro that defines multiple arguments and some
template to expand the macro.

.. code-block:: albatross

   <al-macro name="multi-arg">
   arg1 is "<al-usearg name="arg1">" and
   arg2 is "<al-usearg name="arg2">" and
   the default argument is "<al-usearg>".
   </al-macro>

   <al-expand name="multi-arg">
   This is <al-setarg name="arg2">arg2 content</al-setarg>
   the <al-setarg name="arg1">arg1 content</al-setarg>
   default argument</al-expand>

When the above template is executed the following output is produced.

.. code-block:: none

   arg1 is "arg1 content" and
   arg2 is "arg2 content" and
   the default argument is "This is the default argument".


.. _tug-nestmacro:

Nesting Macros
--------------

Let's revisit the `<http://slashdot.org/>`_ HTML for a story and see how to use
macros to assist in formatting the entire story summary.

Consider the rest of the story summary minus the header (reformatted to fit on
the page):

.. code-block:: html

   <a HREF="http://slashdot.org/search.pl?topic=microsoft">
   <img SRC="http://images.slashdot.org/topics/topicms.gif" WIDTH="75" HEIGHT="55"
   	BORDER="0" ALIGN="RIGHT" HSPACE="20" VSPACE="10" ALT="Microsoft">
   </a>
   <b>Posted by <a HREF="http://www.monkey.org/~timothy">timothy</a>
    on  Sunday July 22, @11:32PM</b><br>
   <font size=2><b>from the hide-the-children-get-the-gun dept.</b></font><br>
   Goldberg's Pants writes: <i>
   "<a HREF="http://www.zdnet.com/zdnn/stories/news/0,4586,2792260,00.html?chkpt=zdnnp1tp02">ZDNet</a>
   and <a HREF="http://www.wired.com/news/technology/0,1282,45427,00.html">Wired</a>
   are both reporting on a new virus that spreads via Outlook. Nothing
   particularly original there, except this virus is pretty unique both
   in how it operates, and what it does, such as emailing random
   documents from your harddrive to people in your address book, and
   hiding itself in the recycle bin which is rarely checked by virus
   scanners."</i> I talked by phone with a user whose machine seemed
   determined to send me many megabytes of this virus 206k at a time; he
   was surprised to find that his machine was infected, as most people
   probably would be. The anti-virus makers have patches, if you are
   running an operating system which needs them.

The first task is to simplify is the topic specific image.  There are a finite
number of topics, and the set of topics does not change much over time.  We
could make effective use of the Albatross ``<al-lookup>`` tag to simplify this
(``<al-lookup>`` is discussed in section :ref:`tug-lookup`):

.. code-block:: albatross

   <al-lookup name="story-topic">
    <al-item expr="'microsoft'">
     <a HREF="http://slashdot.org/search.pl?topic=microsoft">
      <img SRC="http://images.slashdot.org/topics/topicms.gif" WIDTH="75"
           HEIGHT="55" BORDER="0" ALIGN="RIGHT" HSPACE="20" VSPACE="10"
           ALT="Microsoft">
     </a>
    </al-item>
    <al-item expr="'news'">
      :
    </al-item>
   </al-lookup>

Then to display the HTML for the story topic all we would need to do is the
following:

.. code-block:: albatross

   <al-value expr="story.topic" lookup="story-topic">

Next we will simplify the acknowledgement segment:

.. code-block:: html

   <b>Posted by <al-value expr="story.poster" noescape>
    on <al-value expr="story.date" date="%A %B %d, @%I:%M%p"></b><br>
   <font size=2><b>from the <al-value expr="story.dept"> dept.</b></font><br>

Finally we can bring all of these fragments together like this:

.. code-block:: albatross

   <al-macro name="story-summary">
    <al-expand name="story-title"><al-value name="story.title"></al-expand>
    <al-value expr="story.topic" lookup="story-topic">
    <b>Posted by <al-value expr="story.poster">
    on <al-value expr="story.date" date="%A %B %d, @%I:%M%p"></b><br>
    <font size=2><b>from the <al-value expr="story.dept"> dept.</b></font><br>
    <al-value expr="story.summary" noescape>
   </al-macro>

Having defined the macro for formatting a story summary we can format a list of
story summaries like this:

.. code-block:: albatross

   <al-for iter="i" expr="summary_list">
    <al-exec expr="story = i.value()">
    <al-expand name="story-summary"/>
   </al-for>

Notice that all of the macros are referring directly to the ``story`` object
which contains all of the data which pertains to one story.

If you find that your macros are referring to application data by name then you
should consider using a function instead.  Once functions have been implemented
you might be able to use them as well as consider them.


.. _tug-lookup:

Lookup Tables
=============

The example macro used in the previous section introduced a new Albatross tag
called ``<al-lookup>``.  In this section we will look at the tag in more detail.

The ``<al-lookup>`` tag provides a mechanism for translating internal program
values into HTML for display.  This is another way which Albatross allows you to
avoid placing presentation logic in your application.

In a hypothetical bug tracking system we have developed we need to display
information about bugs recorded in the system.  The severity of a bug is defined
by a collection of symbols defined in the :mod:`btsvalues` module.

.. code-block:: python

   TRIVIAL = 0
   MINOR = 1
   NORMAL = 2
   MAJOR = 3
   CRITICAL = 4

While the integer severity levels are OK for use as internal program values they
are not very useful as displayed values.  The obvious way to display a bug
severity would be via the ``<al-value>`` tag.

.. code-block:: albatross

   Severity: <al-value expr="bug.severity">

Unfortunately, this would yield results like this:

.. code-block:: none

   Severity: 1

By using the ``lookup`` attribute of the ``<al-value>`` tag we are able to use
the internal value as an index into a lookup table. The corresponding entry from
the lookup table is displayed instead of the index.

The following is a table which translates the internal program value into HTML
for display.

.. code-block:: albatross

   <al-lookup name="bug-severity">
    <al-item expr="btsvalues.TRIVIAL"><font color="green">Trivial</font></al-item>
    <al-item expr="btsvalues.MINOR">Minor</al-item>
    <al-item expr="btsvalues.NORMAL">Normal</al-item>
    <al-item expr="btsvalues.MAJOR"><font color="red">Major</font></al-item>
    <al-item expr="btsvalues.CRITICAL"><font color="red"><b>Critical</b></font></al-item>
   </al-lookup>

The :mod:`btsvalues` module must be visible when the ``<al-lookup>`` tag is
executed.  You can place the :mod:`btsvalues` module in the the global namespace
of the execution context by importing the :mod:`btsvalues` module in the same
module which creates the :class:`SimpleContext` execution context.  When using
other Albatross execution contexts you would need to import :mod:`btsvalues` in
the module which called :meth:`run_template` or :meth:`run_template_once` to
execute the ``<al-lookup>`` tag.

We invoke the lookup table by using the ``lookup`` attribute of the
``<al-value>`` tag.

.. code-block:: albatross

   Severity: <al-value expr="bug.severity" lookup="bug-severity">

Note that the :mod:`btsvalues` module does not need to be in the namespace at
this point.  The ``expr`` attributes in the ``<a-item>`` tags are evaluated once
when the ``<al-lookup>`` tag is executed.

The ``<al-lookup>`` tag has the same runtime properties as the ``<al-macro>``
tag.  You have execute the tag to register the lookup table with the execution
context.  Once the lookup table has been registered it is available to all
template files executed in the same execution context.

When using Albatross application objects the lookup table is registered in the
application object so can be defined once and then used with all execution
contexts.

Each entry in the lookup table is enclosed in a ``<al-item>`` tag.  The ``expr``
attribute of the ``<al-item>`` tag defines the expression which will be
evaluated to determine the item's table index.  As explained above, the
expression is evaluated when the lookup table is executed, not when the table is
loaded, or looked up (with the rare exception of a lookup being used earlier in
the same template file that it is defined).

It is important to note that the content enclosed by the ``<al-item>`` tag is
executed when the item is retrieved via an ``<al-value>`` tag.  This allows you
to place Albatross tags inside the lookup table that are designed to be
evaluated when the table is accessed.

Finally, any content not enclosed by an ``<al-item>`` tag will be returned as
the result of a failed table lookup.


.. _tug-white:

White Space Removal in Albatross
================================

If you were paying close attention to the results of expanding the macros we
created in section :ref:`tug-content2` you would have noticed that nearly all
evidence of the Albatross tags has disappeared.  It is quite obvious that the
Albatross tags are no longer present.  A little less obvious is removal of
whitespace following the Albatross tags.

Let's have a look at the ``"doc"`` macro again.

   .. literalinclude:: ../samples/templates/content2/macros.html
      :language: albatross

We can get a capture the result of expanding the macro by firing up the Python
interpreter to manually exercise the macro.

   .. literalinclude:: doctest/templ-white1
      :language: pycon

Not only have the ``<al-macro>`` and ``<al-expand>`` tags been removed, the
whitespace that follows those tags has also been removed.  By default Albatross
removes all whitespace following an Albatross tag that begins with a newline.
This behaviour should be familiar to anyone who has used PHP.

Looking further into the result you will note that the ``</body>`` tag is
aligned with the ``<hr noshade>`` tag above it.  This is the result of
performing the ``<al-usearg>`` substitution (which had no content) and removing
all whitespace following the ``<al-usearg>`` tag.

This whitespace removal nearly always produces the desired result, though it can
be a real problem at times.

   .. literalinclude:: doctest/templ-white2
      :language: pycon

The whitespace removal has definitely produced an undesirable result.

You can always get around the problem by joining all of the ``<al-value>`` tags
together on a single line.  Remember that the whitespace removal only kicks in
if the whitespace begins with a newline character.  For our example this would
be a reasonable solution.

   .. literalinclude:: doctest/templ-white3
      :language: pycon

The other way to defeat the whitespace removal while keeping each ``<al-value>``
tag on a separate line would be to place a single trailing space at the end of
each line.  This would be a very bad idea because the next person to modify the
file might remove the space without realising how important it was.

Note that there are trailing spaces at the end of each line in the ``text``
assignment.  This should give you a clue about how bad this technique is.

   .. literalinclude:: doctest/templ-white4
      :language: pycon

A much better way to solve the problem is to explicitly tell the Albatross
parser that you want it to do something different with the whitespace that
follows the first two ``<al-value>`` tags.

   .. literalinclude:: doctest/templ-white5
      :language: pycon

The above variation has told the Albatross interpreter to only strip the
trailing newline, leaving intact the indent on the following line. The following
table describes all of possible values for the ``whitespace`` attribute.

+---------------+-----------------------------------------------+
| Value         | Meaning                                       |
+===============+===============================================+
| ``'all'``     | Keep all following whitespace.                |
+---------------+-----------------------------------------------+
| ``'strip'``   | Remove all whitespace -  this is the default. |
+---------------+-----------------------------------------------+
| ``'indent'``  | Keep indent on following line.                |
+---------------+-----------------------------------------------+
| ``'newline'`` | Remove all whitespace and substitute a        |
|               | newline.                                      |
+---------------+-----------------------------------------------+

Note that when the trailing whitespace does not begin with a newline the
``'strip'`` and ``'indent'`` whitespace directives are treated exactly like
``'all'``.


.. _tug-form1:

Using Forms to Receive User Input
=================================

Nearly all web applications need to accept user input.  User input is captured
by using forms.  We will begin by demonstrating the traditional approach to
handling forms, then in later sections you will see how Albatross can be used to
eliminate the tedious shuffling of application values in and out of form
elements.

Let's start with a program that presents a form to the user and displays to user
response to the form.  The sample program from this section is supplied in the
``samples/templates/form1`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/form1
   python install.py

The CGI program ``form.py`` is shown below.

   .. literalinclude:: ../samples/templates/form1/form.py
      :language: python

There are no surprises here, we are using the standard Python :mod:`cgi` module
to capture the browser request.  We want to display the contents of the request
so it is placed into the execution context.

The ``form.html`` template file is used to display present a form and display
the browser request.

   .. literalinclude:: ../samples/templates/form1/form.html
      :language: albatross

We have placed the form display logic in a separate template file because we
wish to reuse that particularly nasty piece of template. The form display
template is contained in ``form-display.html``.

If you do not understand how the :class:`FieldStorage` class from the :mod:`cgi`
module works, do not try to understand the following template.  Refer to section
:ref:`tug-form2` which contains a small explanation of the :class:`FieldStorage`
class and some Python code that performs the same task as the template.

   .. literalinclude:: ../samples/templates/form1/form-display.html
      :language: albatross

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/form1/form.py>`_.

You will notice that each time you submit the page it comes back with all of the
fields cleared again.

Typically web applications that generate HTML dynamically will hand construct
``<input>`` tags and place application values into the ``value`` attributes of
the input tags.  Since we are using Albatross templates we do not have the
ability to construct tags on the fly without doing some very nasty tricks.
Fortunately Albatross supplies some tags that we can use in place of the
standard HTML ``<input>`` tags.


.. _tug-form2:

Using Albatross Input Tags
==========================

In the previous section we saw how web applications can capture user input from
browser requests.  This section explains how Albatross ``<al-input>`` tags can
be used to take values from the execution context and format them as ``value``
attributes in the HTML ``<input>`` tags sent to the browser.

The sample program from this section is supplied in the
``samples/templates/form2`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/form2
   python install.py

The first change is in the ``form.html`` template file.

   .. literalinclude:: ../samples/templates/form2/form.html
      :language: albatross

We need to place some values into the execution context so that the Albatross
``<al-input>`` tags can display them.  The easiest thing to do is to place the
browser submitted values into the execution context.

The documentation for the Python :mod:`cgi` module is quite good so I will not
try to explain the complete behaviour of the :class:`FieldStorage` class.  The
only behaviour that we need to be aware of for our program is what it does when
it receives more than one value for the same field name.

The :class:`FieldStorage` object that captures browser requests behaves like a
dictionary that is indexed by field name.  When the browser sends a single value
for a field, the dictionary lookup yields an object containing the field value
in the :attr:`value` member.  When the browser sends more than one value for a
field, the dictionary lookup returns a list of the objects used to represent a
single field value.

Using this knowledge, the ``form.py`` program can be modified to merge the
browser request into the execution context.

   .. literalinclude:: ../samples/templates/form2/form.py
      :language: python

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/form2/form.py>`_.

You will notice that your input is sent back to you as the default value of each
form element.

When you use Albatross application objects the browser request is automatically
merged into the execution context for you.


.. _tug-form3:

More on the ``<al-select>`` Tag
===============================

In the previous section we performed a direct translation of the standard HTML
input tags to the equivalent Albatross tags.  In addition to a direct
translation from the HTML form, the ``<al-select>`` tag supports a dynamic form.

In all but the most simple web application you will occasionally need to define
the options in a ``<select>`` tag from internal application values.  In some
ways the dynamic form of the ``<al-select>`` tag is easier to use than the
static form.

The sample program from this section is supplied in the
``samples/templates/form3`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/form3
   python install.py

The form from section :ref:`tug-form2` has been modified to include two
``<al-select>`` tags, and as shown below.

   .. literalinclude:: ../samples/templates/form3/form.html
      :language: albatross

The ``<al-select>`` tags demonstrate the two ways that you can define option
lists in your code using the ``optionexpr`` attribute.  When converting the tag
to HTML the expression in the ``optionexpr`` attribute is evaluated and the
result is used to generate the option list that appears in the generated HTML.

The ``<form.py>`` program has been modified to supply lists of option values.

   .. literalinclude:: ../samples/templates/form3/form.py
      :language: python

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/form3/form.py>`_.

If you view the browser source produced by the two ``<al-select>`` tags you will
see the difference between the way that both option list forms are handled.
Note in particular that the tuples in ``option_list2`` contain an integer value
as the first element.  This is converted to string when it is compared with the
value stored in ``select2`` to determine which option is selected.

The browser request sent to the application will always contain strings for
field values.


.. _tug-stream1:

Streaming Application Output to the Browser
===========================================

By default Albatross buffers all HTML generated from templates inside the
execution context and sends a complete page once the template execution has
completed (via the :meth:`flush_content` method).  The advantage of buffering
the HTML is that applications can handle exceptions that occur during execution
of the template and prevent any partial results leaking to the browser.

Sometimes your application needs to perform operations which take a long time.
Buffering all output while lengthy processing occurs makes the application look
bad.  Albatross lets you use the ``<al-flush>`` tag to mark locations in your
template file where any accumulated HTML should be flushed to the browser.  The
only downside to using this tag is that you lose the ability to completely
insulate the user from a failure in template execution.

The sample program from this section is supplied in the
``samples/templates/stream`` directory and can be installed in your web server
``cgi-bin`` directory by running the following commands.

.. code-block:: none

   cd samples/templates/stream
   python install.py

The ``stream.py`` program is shown below.

   .. literalinclude:: ../samples/templates/stream/stream.py
      :language: python

We have simulated a slow process by building a class that acts like a sequence
of 10 elements that each take one second to retrieve.

We must make sure that we send the HTTP headers before calling the template
execution (:meth:`to_html` method).  This is necessary since the execution of
the template is going to cause HTML to be sent to the browser.

Now let's look at the ``stream.html`` template file that displays the results of
our slow process.

   .. literalinclude:: ../samples/templates/stream/stream.html
      :language: albatross

You can see the program output by pointing your browser at
`<http://www.object-craft.com.au/cgi-bin/alsamp/stream/stream.py>`_.


.. _tug-tree:

Displaying Tree Structured Data
===============================

One of the more powerful tags in the Albatross toolkit is the ``<al-tree>`` tag.
This tag can be used to display almost any data that is tree structured.

The best way to explain the tag is by example.  Consider the
``samples/templates/tree/tree.py`` sample program.  This is a standalone program
that is intended to be run from the command line.

   .. literalinclude:: ../samples/templates/tree/tree.py
      :language: python

The program constructs a tree of :class:`Node` objects then passes the root of
the tree to the ``tree.html`` template for formatting. The
``samples/templates/tree/tree.html`` template file looks like this:

   .. literalinclude:: ../samples/templates/tree/tree.html
      :language: albatross

When you run the program it produces the following result.

.. code-block:: none

   -a
    |-b
    | |-c
    | \-d
    \-e
      |-f
      | \-g
      |   |-h
      |   \-i
      |-j
      \-k
        |-l
        \-m

Internally the ``<al-tree>`` tag uses a special iterator that is an instance of
the :class:`TreeIterator` class.  This iterator performs a pre-order traversal
of the tree returned by the ``expr`` attribute of the tag.  The only requirement
of the tree node objects is that child nodes are stored in the :attr:`children`
sequence member.

The ``<al-tree>`` tag also supports a more powerful lazy loading mode of
operation which is supported by Albatross application objects. Refer to section
:ref:`tag-tree`.

.. rubric:: Footnotes

.. [#] ``HTMLgen`` can be retrieved from
   `<http://starship.python.net/crew/friedrich/HTMLgen/html/main.html>`_  (this URL
   is currently broken - try via the `Wayback Machine
   <http://web.archive.org/web/20060925091645/http://starship.python.net/crew/friedrich/HTMLgen/html/main.html>`_).
   On Debian or Ubuntu Linux you can install the ``python-htmlgen`` package.

