Clever Harold Tutorial
----------------------

Welcome to the wonderful and exciting and hyperbolic world of web
development with Clever Harold.  In this brief introduction, we shall
create a new Clever Harold project, add a program to it, and make a
template for viewing the results of the program.  If we're lucky, we
might even have time to add a data model, so let's not dally!


Installation
============

This tutorial assumes you've already installed Clever Harold and its
dependancies.  If not, jump to the `Installation Instructions`_ and come
back as quickly as possible (we don't want you to miss anything).


New Project
===========

Clever Harold is a collection of WSGI_ components that you can use in
many projects.  You can create a WSGI_ stack yourself in a Python
module and run it with a server, or you can go down the easy road
paved by the `Python Paste`_ family of tools.  In this tutorial, we're
going to take the easy route.

Run the following command to create a new project::

    $ paster init-harold

You'll be prompted for your project details.  Fill them in as best you
can, but don't be afraid to just press Enter and move on -- everything
is editable in your project ``setup.py`` file.  Here's what we entered and
what we're using for the remainder of the tutorial (user-supplied text
shown in bold):

    | Selected and implied templates:
    |     PasteScript#basic_package  A basic setuptools-enabled package
    |     CleverHarold#harold       A Clever Harold project
    | Enter project name: **SheepAircraft**
    | Variables:
    |     package:  sheepaircraft
    |     project:  SheepAircraft
    | Creating template basic_package
    | Enter version (Version (like 0.1)) ['']: **0.9.3.4a**
    | Enter description (One-line description of the package) ['']: **We get lots of French people around here.**
    | Enter keywords (Space-separated keywords/tags) ['']:
    | Enter author (Author name) ['']: **Jean-Brian Zatapathique**
    | Enter author_email (Author email) ['']: **jean@example.com**
    | Enter url (URL of homepage) ['']:
    | Enter license_name (License name) ['']:
    | Enter zip_safe (True/False: if the package can be distributed as a .zip file) [False]:
    | Creating directory ./SheepAircraft
    | ...

There will be a whole bunch of output after the last prompt.  Don't be
alarmed unless you get a traceback.  In the rare occasion you do get a
traceback, ensure you've installed the dependancies and try again.  If
the problem persists, please post a message to the `mailing list`_ and we'll do our best to get you up and running.



Starting the Server
===================

With the project created, we can now run the server and see our new
site.  Continuing from the previous example and directory::

    $ cd SheepAircraft
    $ paster harold

Wasn't that easy?  Now try to view site in your browser.  The default
setup makes it availble at this URL::

    http://127.0.0.1:8080

Take a look around the pages and when you're ready, continue on with
the next step.  You can leave the server running or stop it with
Control+C.  If you stop it, be sure to start it again to complete the
examples.


What's In Here?
===============

Before we write our first program, let's have a look at the files and
directories that the ``paster`` script created for us.

First, it made a *project directory*.  In our example above, this is
named ``SheepAircraft``.  This directory contains all of our project
files, and must be the current directory when we run some of the other
``paster`` script commands.  More on those later.

In the project directory, the ``paster`` script created an egg-info
directory and two setup files (``setup.cfg`` and ``setup.py``).  The
use of the setup files is beyond the scope of this tutorial, but you
can learn more about them in the Python `Distutils documentation`_ and
the `Setuptools documentation`_.

The ``sheepaircraft.ini`` file in the project directory is the mutton
and potatos of our application configuration.  It defines our WSGI
stack, points to our code and templates, defines logging parameters
(or not), and generally controls how our application is run.

Also in the project directory, we have a *package directory* named
``sheepaircraft``.  This is where we'll put our program code,
templates, and static files like images and stylesheets.

.. _Distutils documentation:  http://docs.python.org/lib/module-distutils.html
.. _Setuptools documentation: http://peak.telecommunity.com/DevCenter/setuptools


First Program
=============

Now that we're a mote familiar with what's on disk, let's write a program.

Access the ``controllers`` directory in your project package
directory.  In our example, this is
``./SheepAircraft/sheepaircraft/controllers``.

    **Note About Controllers**

    The default project template names this directory ``controllers``,
    but Clever Harold is most definitely **not** trying to force an
    MVC archictecture on you.  If the name doesn't fit your
    application, simply rename the directory and change the references
    to it in your project configuration file.

In the ``controllers`` directory, create a file named
``hello.py`` and open it with your favorite text editor.  Then
type into it something like this::

    #!/usr/bin/env python

    def get(who='world'):
        return 'Hello, %s.' % who

    get.expose = True

In case you didn't notice, let us point out what's missing from this
example: framework imports!  Clever Harold never requires you import
the ``harold`` package or any other framework module, for that
matter.  Also notice that only thing required to have Clever Harold
pubilsh this function was the ``get.expose = True`` expression.

Once you've saved the file, the code is available at the URL::

    http://127.0.0.1:8080/hello

And::

    http://127.0.0.1:8080/hello/bob
    http://127.0.0.1:8080/hello?who=bob

Clever Harold publishes your classes and functions by mapping the
parameters of HTTP requests to modules in its path.  The parameter
mapping is quite powerful, allowing for any combination of positional,
default, extra-positional, and extra-keyword arguments.  The details
are a bit too much to cover in a tutorial, so please refer to the
`Program Authoring Guide`_ for a complete discussion.


First View
==========

Moving right along, let's write our first view for our program.

Locate the ``views`` directory in your project package directory.  In
our example, this is ``./SheepAircraft/sheepaircraft/views``.  In the
``views`` directory, create a file named ``message.kid``, open it with
your text editor, and fill it with this::

    <html xmlns:py="http://purl.org/kid/ns#">
        <div py:def="main()">
            Message sent:  $${result}.
        </div>
    </html>


And add a ``view`` attribute to your ``get`` method in the
``hello.py`` module::

    #!/usr/bin/env python

    def get(who='world'):
        return 'Hello, %s.' % who

    get.expose = True
    get.view = 'sheepaircraft.views.message'

When done, save both files and access the original URL::

     http://127.0.0.1:8080/hello?who=Tourist

When an exposed callable has a ``view`` attribute (either a string
template, a module name or a module object), the framework will apply
the results of the call to the view.  In our example, it took the
result of the the ``get`` function and rendered it using the named
module.

Let's take a closer look at the view.  The first line sets up the
namespace for the Kid template parser::

     <html xmlns:py="http://purl.org/kid/ns#">

Notice again the lack of imports, extends, or layout attributes!
Clever Harold supplies these for us at runtime.  Repeat less, reuse
more!


Next is our named template function::

          <div py:def="main()">

The site layout in our fresh project renders the content area using a
template function named ``main``, so we override it here by defining a
replacemnt using the same name.

The name ``main`` is totally arbitrary, but to work properly, the
template functions in our view must have the same names as the
template functions in our site-wide layout.

The last interesting line in our view is::

          Message sent:  $${result}.

When we access the view in our browser, ``$${result}`` is replaced with
the value returned from the ``get`` function.  Seems simple enough,
but why is it called ``result``?  Because our ``get`` function didn't
return a dictionary, the framework wrapped it in one and assigned the
value to the ``result`` key.  Had our function returned a dictionary,
the framework would have passed it unmodified to the view, and the
view would then be responsible for accessing the supplied dictionary
keys.

In addition to associating templates with programs, Clever Harold
allows for full template publishing (Kid, Cheetah are currently
supported and more types are planned), and named functions within
templates.  The framework also supports publishing Restructured Text
files and Markdown text files, and will even use the site-wide layout
to do so.  Refer to the `Template Authoring Guide`_ for more
information.


Data Models
===========

If you want to include your data models in your application, the
framework makes it easy.  It supports mixing and matching models of
various types at different points in your URL structure.  

To continue our example, let's create a SQLAlchemy model and integrate
it with our project.  The first step is to define it in our project
configuration file.  To the config, we'll add a section like this::

    [filter:data_provider_dev]
    use = egg:CleverHarold#sqlalchemy_provider
    dsn = sqlite:////parts.db
    models = sheepaircraft.models.parts_inventory sheepaircraft.models.aircraft_forsale

Then we'll change the [pipeline:pipeline_dev] section to include it::

    [pipeline:pipeline_dev]
    pipeline = eval_error
               request_logger
               request_timer
               session_provider
               cache_provider
               debug_info
               data_provider_dev
               views_dev
               code_dev
               default_app

The placement is in the stack is important.  We want it to come before
the templates and code, but after the logging, debuggers and caching
middleware.

After the section is created, we have to fill those modules.  We'll
add these two files to ./sheepaircraft/models:

- parts_inventory.py
- aircraft_forsale.py

For now, let's create both files, but only fill in the first one.
Here's our model in the ``parts_inventory.py`` module::

    #!/usr/bin/env python

    import sqlalchemy.mods.threadlocal
    from sqlalchemy import *


    metadata = DynamicMetaData()

    parts_table = Table('parts', metadata, 
                        Column('id', Integer, primary_key=True),
                        Column('name', String),
                        Column('inventory', Integer, default=0))

    class Part(object):
        @classmethod
        def by_name(cls, name):
            return objectstore.context.current.query(cls).select(like(name))

	def save(self):
            return objectstore.context.current.save(self)

        def flush(self):
            return objectstore.context.current.flush([self, ])

    mapper(Part, parts_table)


    def populate():
        wheels = Part()
        wheels.name = 'Wizzo Widget Works Wheels'
        wheels.inventory = 38
        wheels.save()
        wheels.flush()


A few notes are in order:

- The database provider will connect the object ``objectstore`` to a new
  session every time our application is called.  The ``objectstore`` object
  is installed and imported from sqlalchemy.

- We created a module-level object called ``metadata``.  The database provider
  will connect this object for us when the server starts.

- We added a ``populate`` function that the framework can call from
  script to fill in default data after the model is constructed.

- The Part class defines methods that use ``objectstore``, the
  module-level, thread-aware SQLAlchemy session.  There are other ways
  to implement session use, but this method works without too much
  effort.

- The ``populate`` method saved and flushed it's object explicitly.
  In application code, you don't have to flush explicity because the
  data provider does that automatically at the end of every successful
  request.  You can flush the session manually if you need to, of
  course.


To use the model within your templates and code, simply import it.
Let's add a module in the controllers directory named
``part_search.py``, and fill it in like this::

    #!/usr/bin/env python

    from sheepaircraft.models.parts_inventory import Part

    def get(name):
        return dict(parts=Part.by_name(name))

    get.expose = True
    get.view = """
    <html xmlns:py="http://purl.org/kid/ns#">
        <div py:def="main()">
        <h1>Parts</h1>
        <div py:for="part in parts">
            <b>$$part.id</b>: $$part.name ($$part.inventory available)
        </div>
        </div>
    </html>
    """

Now that the configuration is updated, the models are defined, and a
view is in place, we have one thing to do, and that's initialize the
database.  The framework installs a command to do this with the paster
script.  To run it for our models, we would do this from a terminal in
our project directory::

    $ paster recreate-models -d -i

The script loads reads the default database section, connects that
models in it with our connection string, and then creates the tables
and fills them.  The ``-d`` switch tells the command to drop any
tables before starting, and ``-i`` tells it to continue working when
it encounters an exception.  

And now our data model is configured, defined, and hooked into our
code.  That wasn't so bad, was it?  To view our work try the part_search url::

    http://127.0.0.1:8080/part_search/wheels


From here, we would build out the data model, fill the other tables,
relations, and mapping classes.  After editing tables, we'll run the
recreate-models command again to install the changes.


Next Steps
----------

We hope you've enjoyed the tutorial, and we hope you've learned how
simple Clever Harold tries to make web applications.  There's plenty
more to learn about a complete Clever Harold application, and you're
invited to continue the journey with any or all of these:

- `Database Integration Guide`_
- `Program Authoring Guide`_
- `Template Authoring Guide`_
- `Caching Support`_
- `Session Support`_
- `Form Authoring Guide`_


.. _Program Authoring Guide: /documentation/programs
.. _Template Authoring Guide:  /documentation/templates
.. _Database Tutorial: /documentation/database
.. _Caching Support: /documentation/caching
.. _Session Support: /documentation/sessions
.. _WSGI:  http://www.python.org/dev/peps/pep-0333/
.. _Python Paste:  http://www.pythonpaste.org/
.. _mailing list:  http://groups.google.com/group/cleverharold/
.. _Installation Instructions:  /documentation/installation
.. _Database Integration Guide: /documentation/databases
.. _Form Authoring Guide: /documentation/forms
