4.8 Random Access Applications
Description: Random Access Applications
Keywords: albatross

#
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')