3.8 Using Forms to Receive User Input

#
3.8 Using Forms to Receive User Input

Nearly all web applications need to accept user input. User input is captured by using forms. We will begin by demonstrating the traditional approach to handling forms, then in later sections you will see how Albatross can be used to eliminate the tedious shuffling of application values in and out of form elements.

Let's start with a program that presents a form to the user and displays to user response to the form. The sample program from this section is supplied in the `samples/templates/form1` directory and can be installed in your web server `cgi-bin` directory by running the following commands.

    cd samples/templates/form1
    python install.py

The CGI program `form.py` is shown below.

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

    ctx = SimpleContext('.')
    ctx.locals.form = cgi.FieldStorage()

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

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

There are no surprises here, we are using the standard Python `cgi` module to capture the browser request. We want to display the contents of the request so it is placed into the execution context.

The `form.html` template file is used to display present a form and display the browser request.

    <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>

We have placed the form display logic in a separate template file because we wish to reuse that particularly nasty piece of template. The form display template is contained in `form-display.html`.

If you do not understand how the `FieldStorage` class from the `cgi` module works, do not try to understand the following template. Refer to section 3.9 which contains a small explanation of the `FieldStorage` class and some Python code that performs the same task as the template.

    <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>

You can see the program output by pointing your browser at http://www.object-craft.com.au/cgi-bin/alsamp/form1/form.py.

You will notice that each time you submit the page it comes back with all of the fields cleared again.

Typically web applications that generate HTML dynamically will hand construct `<input>` tags and place application values into the `value` attributes of the input tags. Since we are using Albatross templates we do not have the ability to construct tags on the fly without doing some very nasty tricks. Fortunately Albatross supplies some tags that we can use in place of the standard HTML `<input>` tags.