Differences between revisions 1 and 4 (spanning 3 versions)
Revision 1 as of 2008-08-28 07:04:41
Size: 5014
Comment:
Revision 4 as of 2008-08-28 07:16:48
Size: 11489
Comment:
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:

----
Line 28: Line 30:

Albatross uses a Open Source BSD license that permits most uses. The Albatross 1.00 license is below:
Line 29: Line 33:

Albatross uses a Open Source BSD license that permits most uses. The Albatross 1.00 license is below:
Line 65: Line 67:
Alternatively, you can join the Albatross-Users mailing list. For instructions on subscribing, go HERE Alternatively, you can join the Albatross-Users mailing list. For instructions on subscribing, go [https://www.object-craft.com.au/cgi-bin/mailman/listinfo/albatross-users HERE].
Line 82: Line 84:

----

= Installation =
== Does Albatross work under Unix? ==
Of course!

== Does Albatross work under Windows? ==
Yes.

== What version of Python is required to run Albatross? ==

Albatross works with all versions of Python from version 2.3 onwards. It has not yet been ported to Python 3.

== What other packages do I need to have before I can install Albatross? ==

You will probably want a web server, although it's possible to use the templating functionality outside a web server, and Albatross includes a stand-alone deployment mode that is suitable for limited use without a web server.

To rebuild the documentation, you will need:
LATEX
latex2html
Python source - mkhowto and LATEX styles
dia

We recommend you use the pre-formatted manuals available from http://www.object-craft.com.au/projects/albatross/.

----

= Templates =

== Can I nest macros? ==

Yes, although you will need to explicitly pass any arguments through. For example:
{{{#!python
    <al-macro name="sub">
        This is the submacro, its argument is:
        <al-usearg name="subarg" />
    </al-macro>
    <al-macro name="main">
        This is the main macro.
        <al-expand name="sub">
            <al-setarg name="subarg">
                <al-usearg name="mainarg" />
            </al-setarg>
        </al-expand>
    </al-macro>
    <al-expand name="main">
        <al-setarg name="mainarg">
            Whatever
        </al-setarg>
    </al-expand>
}}}

== What happens to attributes on Albatross tags that Albatross doesn't recognise? ==
Attributes that Albatross doesn't recognise are passed through to the generated HTML unchanged.

== I need to internationalise my templates? ==

Dave suggested the following (untested) idea:

    You could override the execution context load_template() and
    load_template_once() to alter the template name based upon the
    language header from the browser.

{{{#!python
    class MyCtx(SimpleAppContext):
        def language_vary(self, name):
            language = self.request.get_header('Accept-Language')
            if language:
                return os.path.join(string.split(language, ',')[0], name)
            return name
        def load_template(self, name):
            name = self.language_vary(name)
            return SimpleAppContext.load_template(name)
        def load_template_once(self, name):
            name = self.language_vary(name)
            return SimpleAppContext.load_template_once(name)
}}}
    With a bit of effort you could make it more robust.

----

= Application model =

== How do I capture the output from processing my templates? ==

You may want your template output to go somewhere other than stdout. If so, use ctx.push_content_trap() and ctx.pop_content_trap():

{{{#!python
    ctx.push_content_trap()
    tmpl = ctx.load_template(filename)
    tmpl.to_html(ctx)
    ctx.flush_content()
    results = ctx.pop_content_trap()
}}}
Technically, calling push_content_trap() saves the current list off fragments on a stack and then clears the list. When you call pop_content_trap() the contents of the list and joined and returned and the previous fragment list is restored from the stack. This is used internally for arguments to macro expansion and sometimes for options to the select tag.

== Can Albatross look after my logging? ==
Albatross doesn't help you with logging (yet), although traditionally stderr goes to the web server error log.

The easiest way to add logging support yourself would be to make your own subclass of one of the Context objects, and add your logging methods to this.

A simple example:
{{{#!python
    class LogMixin:
        def log(self, s):
            sys.stderr.write('%s\n' % s)
            sys.stderr.flush()
    class AppContext(albatross.SimpleAppContext, LogMixin):
            ...
    ctx.log('log message')
}}}
== Can I use the cgitb module with Albatross? ==
"cgitb" is a module that aids in the reporting of uncaught exceptions from within CGI scripts. It is distributed as a standard part of Python as of version 2.2. Because Albatross handles it's own exceptions, however, cgitb never gets a chance to report them.

Dave suggests overriding the handle_exception() method would work, although this is untested:
{{{#!python
    import cgitb
    from albatross import SimpleApp
    class MyApp(SimpleApp):
        def handle_exception(self, req):
            cgitb.handler()
}}}

== When are the page methods page_process, page_enter, page_leave, and page_display called? ==

For a page class called "blah", blah.page_enter() is called once after the previous page class calls ctx.set_page('blah'), and blah.page_display() is then called (and called each time the page is redisplayed - on reload, for example).

When the user submits some data, blah.page_process() is called. page_process() can act on the data, save it, or request the application to move to a new page (ctx.set_page()).

If the application remains on the "blah" page, blah.page_display() is called. If set_page() was called, blah.page_leave() is called, and process starts again with the new page class.

Note that you don't need to provide all four methods - if not provided, they default to sensible actions in each case.

In page_enter(), you would put one time initialisation (setting default values for form fields for example).
{{{#!python
    def page_enter(ctx):
        ctx.locals.diagnostic = ''
        ctx.locals.whatever = load_whatever()
        ctx.add_session_vars('whatever')
}}}
In page_display(), you might initialise more form fields (ones derived from external data, maybe), for example:
{{{#!python
    def page_display(ctx):
        ctx.locals.load_setting_name = ctx.locals.settings.get_current_name()
        return ctx.run_template('change_parameters.html')
}}}
In page_process(), you act on the user's form submission:
{{{#!python
    def page_process(ctx):
        if ctx.req_equals('submit'):
            if ctx.locals.username == '':
                ctx.locals.diagnostic = 'You must enter a username'
        else:
            ctx.locals.diagnostic = ''
}}}
In page_leave(), you might perform cleanup:
{{{#!python
    def page_leave(ctx):
        ctx.remove_session_vars('whatever')
}}}

TableOfContents(2)


General

What is Albatross

Albatross is a small and flexible toolkit for developing highly stateful web applications. The toolkit provides the following:

  • Browser based sessions via automatically generated hidden form fields (cryptographically signed to ensure integrity).
  • Server side sessions via a session server or file based session store.
  • Powerful and extensible templating system which promotes separation of presentation and implementation for improved program maintainability.
  • Pagination of sequences and tree browsing are handled implicitly in the templating system.
  • Macros allow repeated HTML and special effects HTML to be defined in one location.
  • Lookup tables translate internal program values to arbitrary template code.
  • Applications can be deployed as either CGI programs or as mod_python module with minor changes to program mainline. Custom deployment can be achieved by developing your own Request class.
  • Highly modular application framework which is flexible and extensible which allows many different application construction models. Eight Application classes are provided while many more are possible.
  • Comprehensive documentation including many installable samples.

A primary design goal of Albatross is that it be small and easy to use and extend. Most of the toolkit is constructed from a collection of mixin classes. You are encouraged to look at the code and to think of new ways to combine the Albatross mixin classes with your own classes.

Object Craft developed Albatross because there was nothing available with the same capabilities which they could use for consulting work. For this reason the toolkit is important to Object Craft and so is actively maintained and developed.

What language is Albatross written in?

Albatross is written in Python, a powerful, but easy to learn, object-oriented scripting language. For more information on Python, go to http://www.python.org/

What license does Albatross use?

Albatross uses a Open Source BSD license that permits most uses. The Albatross 1.00 license is below:

Copyright (C) 2002, Object Craft P/L, Melbourne, Australia.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

    * Neither the name of Object Craft nor the names of its contributors may be
      used to endorse or promote products derived from this software without
      specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

I can't find an answer to my question here?

Ask us - send your question to albatross@object-craft.com.au.

Alternatively, you can join the Albatross-Users mailing list. For instructions on subscribing, go [https://www.object-craft.com.au/cgi-bin/mailman/listinfo/albatross-users HERE].

Is commercial support available?

Definitely! Contact enquiries@object-craft.com.au for more information.

Can you write my application for me?

Object Craft would be happy to talk to you about your requirements. Please contact enquiries@object-craft.com.au.

It is worth noting, however, that because Albatross is Open Source and written with ease of understanding in mind, any skilled python developer will also be able to help you.

What projects has Albatross been used in?

Among other things, Albatross has been used to:

  • provide a Web interface to a mortality data analysis system which has been developed by the Centre for Epidemiology and Research in the New South Wales Department of Health. A series of related epidemiologic applications, all using Albatross, are currently in the planning stage. For more information please contact Dr Tim Churches.

Does Albatross have a mailing list or discussion group?

Yes - to subscribe, go to https://www.object-craft.com.au/cgi-bin/mailman/listinfo/albatross-users


Installation

Does Albatross work under Unix?

Of course!

Does Albatross work under Windows?

Yes.

What version of Python is required to run Albatross?

Albatross works with all versions of Python from version 2.3 onwards. It has not yet been ported to Python 3.

What other packages do I need to have before I can install Albatross?

You will probably want a web server, although it's possible to use the templating functionality outside a web server, and Albatross includes a stand-alone deployment mode that is suitable for limited use without a web server.

To rebuild the documentation, you will need: LATEX latex2html Python source - mkhowto and LATEX styles dia

We recommend you use the pre-formatted manuals available from http://www.object-craft.com.au/projects/albatross/.


Templates

Can I nest macros?

Yes, although you will need to explicitly pass any arguments through. For example:

   1     <al-macro name="sub">
   2         This is the submacro, its argument is:
   3         <al-usearg name="subarg" />
   4     </al-macro>
   5     <al-macro name="main">
   6         This is the main macro.
   7         <al-expand name="sub">
   8             <al-setarg name="subarg">
   9                 <al-usearg name="mainarg" />
  10             </al-setarg>
  11         </al-expand>
  12     </al-macro>
  13     <al-expand name="main">
  14         <al-setarg name="mainarg">
  15             Whatever
  16         </al-setarg>
  17     </al-expand>

What happens to attributes on Albatross tags that Albatross doesn't recognise?

Attributes that Albatross doesn't recognise are passed through to the generated HTML unchanged.

I need to internationalise my templates?

Dave suggested the following (untested) idea:

  • You could override the execution context load_template() and load_template_once() to alter the template name based upon the language header from the browser.

   1     class MyCtx(SimpleAppContext):
   2         def language_vary(self, name):
   3             language = self.request.get_header('Accept-Language')
   4             if language:
   5                 return os.path.join(string.split(language, ',')[0], name)
   6             return name
   7         def load_template(self, name):
   8             name = self.language_vary(name)
   9             return SimpleAppContext.load_template(name)
  10         def load_template_once(self, name):
  11             name = self.language_vary(name)
  12             return SimpleAppContext.load_template_once(name)
  • With a bit of effort you could make it more robust.


Application model

How do I capture the output from processing my templates?

You may want your template output to go somewhere other than stdout. If so, use ctx.push_content_trap() and ctx.pop_content_trap():

   1     ctx.push_content_trap()
   2     tmpl = ctx.load_template(filename)
   3     tmpl.to_html(ctx)
   4     ctx.flush_content()
   5     results = ctx.pop_content_trap()

Technically, calling push_content_trap() saves the current list off fragments on a stack and then clears the list. When you call pop_content_trap() the contents of the list and joined and returned and the previous fragment list is restored from the stack. This is used internally for arguments to macro expansion and sometimes for options to the select tag.

Can Albatross look after my logging?

Albatross doesn't help you with logging (yet), although traditionally stderr goes to the web server error log.

The easiest way to add logging support yourself would be to make your own subclass of one of the Context objects, and add your logging methods to this.

A simple example:

   1     class LogMixin:
   2         def log(self, s):
   3             sys.stderr.write('%s\n' % s)
   4             sys.stderr.flush()
   5     class AppContext(albatross.SimpleAppContext, LogMixin):
   6             ...
   7     ctx.log('log message')

Can I use the cgitb module with Albatross?

"cgitb" is a module that aids in the reporting of uncaught exceptions from within CGI scripts. It is distributed as a standard part of Python as of version 2.2. Because Albatross handles it's own exceptions, however, cgitb never gets a chance to report them.

Dave suggests overriding the handle_exception() method would work, although this is untested:

   1     import cgitb
   2     from albatross import SimpleApp
   3     class MyApp(SimpleApp):
   4         def handle_exception(self, req):
   5             cgitb.handler()

When are the page methods page_process, page_enter, page_leave, and page_display called?

For a page class called "blah", blah.page_enter() is called once after the previous page class calls ctx.set_page('blah'), and blah.page_display() is then called (and called each time the page is redisplayed - on reload, for example).

When the user submits some data, blah.page_process() is called. page_process() can act on the data, save it, or request the application to move to a new page (ctx.set_page()).

If the application remains on the "blah" page, blah.page_display() is called. If set_page() was called, blah.page_leave() is called, and process starts again with the new page class.

Note that you don't need to provide all four methods - if not provided, they default to sensible actions in each case.

In page_enter(), you would put one time initialisation (setting default values for form fields for example).

   1     def page_enter(ctx):
   2         ctx.locals.diagnostic = ''
   3         ctx.locals.whatever = load_whatever()
   4         ctx.add_session_vars('whatever')

In page_display(), you might initialise more form fields (ones derived from external data, maybe), for example:

   1     def page_display(ctx):
   2         ctx.locals.load_setting_name = ctx.locals.settings.get_current_name()
   3         return ctx.run_template('change_parameters.html')

In page_process(), you act on the user's form submission:

   1     def page_process(ctx):
   2         if ctx.req_equals('submit'):
   3             if ctx.locals.username == '':
   4                 ctx.locals.diagnostic = 'You must enter a username'
   5         else:
   6             ctx.locals.diagnostic = ''

In page_leave(), you might perform cleanup:

   1     def page_leave(ctx):
   2         ctx.remove_session_vars('whatever')

None: FAQ (last edited 2011-02-15 06:05:17 by localhost)