4.8 Random Access Applications

In the popview application the server is in complete control of the sequence of pages that are served to the browser. In some applications you want the user to be able to bookmark individual pages for later retrieval in any desired sequence. Albatross provides application classes built with the RandomPageModuleMixin class for this very purpose.

The random sample is provided to demonstrate the use of the RandomModularSessionApp class. Use the install.py script to install the sample.

cd samples/random
python install.py

The complete mainline of the randompage.py sample is shown below.

#!/usr/bin/python
from albatross import RandomModularSessionApp
from albatross.cgiapp import Request

app = RandomModularSessionApp(base_url='randompage.py',
                              page_path='pages',
                              start_page='tree',
                              secret='-=-secret-=-',
                              session_appid='random')

if __name__ == '__main__':
    app.run(Request())

When processing the browser request the application determines which page to serve to the browser by inspecting the URL in the browser request. The page identifier is taken from the part of the URL which follows the base_url argument to the constructor. If the page identifier is empty then the application serves the page identified by the start_page argument to the constructor.

If you point your browser at http://www.object-craft.com.au/cgi-bin/alsamp/random/randompage.py you will notice that the server has redirected your browser to the start page.

The sample program defines two pages which demonstrate two different ways to direct user navigation through the application.

The tree.html page template uses a form to capture user input.

<html>
<head><title>Here is a Tree</title></head>
<body>
<al-lookup name="indent">
 <al-item expr="0">  </al-item>
 <al-item expr="1"> |</al-item>
 <al-item expr="2"> \</al-item>
</al-lookup>
<h1>Here is a Tree</h1>
<al-form method="post">
<pre>
<al-tree iter="n" expr="tree">
 <al-for iter="c" expr="range(n.depth())">
  <al-value expr="n.line(c.value())" lookup="indent">
 </al-for>
 -<al-input type="checkbox" alias="n.value().selected">
  <al-value expr="n.value().name" whitespace="newline">
</al-tree>
</pre>
<al-input type="submit" name="save" value="Save">
<al-input type="submit" name="paginate" value="To Paginate Page">
</al-form>
</body>
</html>

During conversion to HTML the <al-form> tag automatically places the name of the current page into the action attribute. This makes the browser send the response back to the same page module (tree.py).

from utils import Node

def page_display(ctx):
    ctx.run_template('tree.html')

def page_process(ctx):
    if ctx.req_equals('paginate'):
        ctx.redirect('paginate')
    if not hasattr(ctx.locals, 'tree'):
        ctx.locals.tree \
            = Node('a', [Node('a', [Node('a'),
                                    Node('b')]),
                         Node('b', [Node('a', [Node('a', [Node('a'),
                                                          Node('b')])]),
                                    Node('b'),
                                    Node('c', [Node('a'),
                                               Node('b')])])])
        ctx.add_session_vars('tree')

When the application receives the paginate request it uses the redirect() method to direct the browser to a new page.

The paginate.html page template uses a URLs to capture user input.

<html>
 <head><title>Pagination Example</title></head>
 <body>
  <h1>This is a list with pagination...</h1>

  <al-for iter="i" expr="data" pagesize="10" prepare/>
  <al-if expr="i.has_prevpage()">
   <al-a prevpage="i">prev</al-a>
  </al-if>
  <al-for iter="i" pagesize="10">
   <al-if expr="i.count()">,</al-if> <al-value expr="i.value()">
  </al-for>
  <al-if expr="i.has_nextpage()" whitespace>
   <al-a nextpage="i">next</al-a>
  </al-if>
  <p>
  <al-a href="tree">To Tree Page</al-a>
 </body>
</html>

During conversion to HTML the <al-a> tag automatically translates the href="tree" attribute into a URL which requests the tree page from the application. Since the browser is doing all of the work, the paginate.py module which handles the paginate page is very simple.

def page_display(ctx):
    ctx.locals.data = range(100)
    ctx.run_template('paginate.html')