Python Web Programming

Albatross


Obtaining and Installing

Obtained from:

http://www.object-craft.com.au/projects/albatross/download.html

Installed via:

tar xzvf albatross-1.40.tar.gz
cd albatross-1.40
su
python setup.py install


Test Programs

Program 1

A first program is installed thusly:

cd albatross-1.40
cd samples/templates/simple2
su
python install.py
This puts two files in the /var/www/cgi-bin/alsamp/simple2 directory.

simple.html

<html>
 <head>
  <title>My CGI application</title>
 </head>
 <body>
  Hello from my second simple CGI application!
 </body>
</html>
simple.py

#!/usr/bin/python
from albatross import SimpleContext

#  Specifies the directory - in this case ".", or the present working directory - from
#  which the template file(s) will be loaded.
ctx = SimpleContext('.')

#  Specifies the specific template file (simple.html) to be loaded.
templ = ctx.load_template('simple.html')

#  Execute the template.
templ.to_html(ctx)

#  Output the HTTP headers.
print 'Content-Type: text/html'
print
ctx.flush_content()

This can be accessed at:

http://csanady.tamu.edu/cgi-bin/alsamp/simple2/simple.py


Program 2

A second program that introduces using application data into Albatross is:

cd samples/templates/simple3
su
python install.py

The template file simple.py is:

<html>
 <head>
  <title>The CGI environment</title>
 </head>
 <body>
  <table>

#  The <al-for> tag iterates over the list of environment variable
#  names in the keys value from ctx.local.keys.  The iter value name
#  specifies the name of the iterator used to retrieve values.

   <al-for iter="name" expr="keys">
    <tr>

#  The content enclosed by <al-for> is evaluated for each value in
#  the sequence returned by evaluating the "expr" attribute.  The <al-value> tag
#  retrieves values from the execution context.  The "expr" attribute can contain any
#  Python expression that can legally passed to the eval() function.

     <td><al-value expr="name.value()"></td>
     <td><al-value expr="environ[name.value()]"></td>
    <tr>
   </al-for>
  </table>
 </body>
</html>

and the CGI program is:

#!/usr/bin/python
import os
from albatross import SimpleContext

ctx = SimpleContext('.')
templ = ctx.load_template('simple.html')

#  Constructs a list of all defined environment variables os.environ and
#  and places it in the keys variable.

keys = os.environ.keys()

#  Sorts the keys variable.

keys.sort()

#  The Albatross execution context (ctx) is constructed with an empty object (locals)
#  that is used as a conduit between the application and the toolkit.   It is used as
#  local namespace for expressions evaluated in template files.  We make the environment
#  available to the template file by assigning names that can be referenced by
#  the template file (keys, environ).

ctx.locals.keys = keys
ctx.locals.environ = os.environ

templ.to_html(ctx)

print 'Content-Type: text/html'
print
ctx.flush_content()

The Python environment variables are os.environ. A brief Python sessions demonstrates:

import os
os.environ
{'TERM_PROGRAM_VERSION': '240.2', 'LOGNAME': ... COMMAND_MODE': 'unix2003'}
keys = os.environ.keys
keys
['TERM_PROGRAM_VERSION', 'LOGNAME', ... , 'COMMAND_MODE']

This example can be accessed at:

http://csanady.tamu.edu/cgi-bin/alsamp/simple3/simple.py

and returns the following:

DOCUMENT_ROOT  	/var/www/html
GATEWAY_INTERFACE 	CGI/1.1
HTTP_ACCEPT 	text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
...
SERVER_SIGNATURE 	
Apache/2.0.52 (Fedora) Server at csanady.tamu.edu Port 80
SERVER_SOFTWARE Apache/2.0.52 (Fedora)

We can simplify the above example - as well as separating the presentation logic from the application - using the flexibility of the "expr" attribute. We rewrite the CGI program as:

#!/usr/bin/python
import os
from albatross import SimpleContext

ctx = SimpleContext('.')
templ = ctx.load_template('simple.html')

ctx.locals.environ = os.environ

templ.to_html(ctx)

print 'Content-Type: text/html'
print
ctx.flush_content()

and rewrite the template file as:

<html>
 <head>
  <title>The CGI environment</title>
 </head>
 <body>
  <table>
   <al-exec expr="keys = environ.keys(); keys.sort()">
   <al-for iter="name" expr="keys">
    <tr>
     <td><al-value expr="name.value()"></td>
     <td><al-value expr="environ[name.value()]"></td>
    <tr>
   </al-for>
  </table>
 </body>
</html>

In this example only the environ variable is passed from the application to the toolkit.


Program 3 - Introducing Forms In the forms example we learn how to create and store data input from forms.

The CGI program form.py is:

#!/usr/bin/python
import cgi
from albatross import SimpleContext

ctx = SimpleContext('.')

#  The variables chosen in the forms are saved in and accessed via the FieldStorage class from
#  the CGI module.  The FieldStorage object behaves like a dictionary that is indexed by
#  field name.

ctx.locals.form = cgi.FieldStorage()

templ = ctx.load_template('form.html')
templ.to_html(ctx)

print 'Content-Type: text/html'
print
ctx.flush_content()

and the template file form.html presents an input form to obtain values and displays the values when they are submitted.

<html>
 <head>
  <title>Display Form Input</title>
 </head>
 <body>
  Input some values to the following form and press the submit button.
  <form method="post" action="form.py">
   Text field: <input name="text"><br>
   Singleton checkbox: <input type="checkbox" name="singleton"><br>
   Checkbox group:
   <input type="checkbox" name="group" value="check1">
   <input type="checkbox" name="group" value="check2"><br>
   Radio buttons:
   <input type="radio" name="radio" value="radio1">
   <input type="radio" name="radio" value="radio2"><br>
   Option menu: <select name="select"><option>option1<option>option2<option>option3</select>
   <input type="submit" value="submit">
  </form>
  <al-include name="form-display.html">
 </body>
</html>

The form-display.html file contains the logic for displaying the values chosen via form.html.

<al-for iter="f" expr="form.keys()">
 <al-exec expr="field = form[f.value()]">
 <al-if expr="type(field) is type([])">
  Field <al-value expr="f.value()"> is list:
  <al-for iter="e" expr="field">
   <al-exec expr="elem = e.value()">
   <al-if expr="e.index() > 0">, </al-if>
   <al-value expr="elem.value">
  </al-for>
 <al-else>
  Field <al-value expr="f.value()"> has a single value:
  <al-value expr="field.value">
 </al-if>
 <br>
</al-for>

Sending Non-HTML Content

From http://www.object-craft.com.au/projects/albatross/wiki/Sending_non-HTML_content:

This example sends the file named in ctx.locals.filename to the browser, but the content could be a dynamically generated PDF file.

import mimetypes

def page_display(ctx):

    # Decide which file to send back
    filename = ctx.locals.filename

    # Read the file's content (ignores errors for brevity)
    data = file(filename).read()
    # Find the MIME type
    mime_type = mimetypes.guess_type(filename)[0]
    # Set the content-type header

    # Set the MIME type and send the data
    ctx.set_header('Content-Type', mime_type)
    ctx.send_content(data)

Python Web Without Albatross

An example of web programming without Albatross is at:

http://www.linux.com/archive/feature/136602

and is:
#!/usr/bin/python
import cgi
print "Content-type: text/html"
print
form = cgi.FieldStorage()
laptops = form.getvalue('laptops','0')
desktops = form.getvalue('desktops','0')
print """
<html>
<body>
<form action='second.py'>
How many laptops do you own? 
<input type='radio' checked name='laptops' value='0' />0 
<input type='radio' name='laptops' value='1' />1 
<input type='radio' name='laptops' value='2' />2
<p>
How many desktops do you own? 
<input type='radio' checked name='desktops' value='0' />0 
<input type='radio' name='desktops' value='1' />1 
<input type='radio' name='desktops' value='2' />2
<p>
<input type='submit' />
<p>
You own %d computers.
</form>
</body>
</html>""" % (int(laptops)+int(desktops))

WCS - OWSlib

Commands illustrating the capabilities of OWSlib WCS. This is sparsely documented elsewhere, with the following developed mostly via trial and (extensive) error. Some documentation can be found at:

http://home.badc.rl.ac.uk/spascoe/ndg3/ds_workshop/cows.html
http://pypi.python.org/pypi/OWSLib/

#  Import the appropriate routines from the OWSlib package.

from owslib.wcs import WebCoverageService

#  Create an object containing the virtual concatenated file on the server.

#wcs=WebCoverageService('http://megara.tamu.edu:8080/thredds/wcs/gcoos/seadas?service=WCS&version=1.0.0')
wcs=WebCoverageService('http://megara.tamu.edu:8080/thredds/wcs/gcoos/seadas_sst?service=WCS&version=1.0.0')

wcs.identification.service
wcs.identification.title
wcs.identification.abstract
wcs.identification.keywords
wcs.identification.fees
wcs.identification.accessConstraints

wcs.provider.name
wcs.provider.url
wcs.provider.contact.name
wcs.provider.contact.email
wcs.provider.contact.organization
wcs.provider.contact.address
wcs.provider.contact.city
wcs.provider.contact.region
wcs.provider.contact.postcode
wcs.provider.contact.country

#  Find out what's available from the server.

wcs.contents
{'cloud_mask': ,
 'l2_flags': ,
 'seadas_sst': }

#  Create and obtain an object representing the metaedata of the seadas_sst coverage.

sst = wcs['seadas_sst']

#  Get the spatial extent of the coverage.

sst.boundingBoxWGS84
(-98.0, 18.010390000000001, -79.010989999999993, 31.0)

#  Get the temporal extent of the coverage.

sst.timelimits
['2009-10-12T02:59:47Z', '2010-06-21T07:44:36Z']

#  Get all of the time positions of the coverage.
sst.timepositions
['2009-10-12T02:59:47Z', '2009-10-12T04:38:06Z', ... '2010-06-24T08:15:43Z']

#  Get the supported formats for the coverage.

sst.supportedFormats
['GeoTIFF', 'GeoTIFF_Float', 'NetCDF3']

#  Get the support CRS.
sst.supportedCRS
['OGC:CRS84']

#  Use the above info to formulate a GetCoverage request.

output=wcs.getCoverage(identifier='seadas_sst',time=['2009-10-12T02:59:47Z'],bbox=(-90,-85,20,25),format='NetCDF3')

#  Write the coverage file to disk as file test.nc.

f=open('test.nc','wb')
f.write(output.read())
f.variables