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 random.py sample is shown below.
#!/usr/bin/python from albatross import RandomModularSessionApp from albatross.cgiapp import Request app = RandomModularSessionApp(base_url = 'random.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/random.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).
node_num = 0 class Node: def __init__(self, name, children = None): self.name = name if children is not None: self.children = children self.selected = 0 global node_num self.node_num = node_num node_num = node_num + 1 def albatross_alias(self): return 'node%d' % self.node_num 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')