11.2.3 Higher Level Interface

Python PEP

11.2.3 Higher Level Interface

New in version 2.2.

The previous section explains how to read CGI form data using the FieldStorage class. This section describes a higher level interface which was added to this class to allow one to do it in a more readable and intuitive way. The interface doesn't make the techniques described in previous sections obsolete -- they are still useful to process file uploads efficiently, for example.

The interface consists of two simple methods. Using the methods you can process form data in a generic way, without the need to worry whether only one or more values were posted under one name.

In the previous section, you learned to write following code anytime you expected a user to post more than one value under one name:

item = form.getvalue("item")
if isinstance(item, list):
    # The user is requesting more than one item.
else:
    # The user is requesting only one item.

This situation is common for example when a form contains a group of multiple checkboxes with the same name:

<input type="checkbox" name="item" value="1" />
<input type="checkbox" name="item" value="2" />

In most situations, however, there's only one form control with a particular name in a form and then you expect and need only one value associated with this name. So you write a script containing for example this code:

user = form.getvalue("user").upper()

The problem with the code is that you should never expect that a client will provide valid input to your scripts. For example, if a curious user appends another "user=foo" pair to the query string, then the script would crash, because in this situation the getvalue("user") method call returns a list instead of a string. Calling the toupper() method on a list is not valid (since lists do not have a method of this name) and results in an AttributeError exception.

Therefore, the appropriate way to read form data values was to always use the code which checks whether the obtained value is a single value or a list of values. That's annoying and leads to less readable scripts.

A more convenient approach is to use the methods getfirst() and getlist() provided by this higher level interface.

This method always returns only one value associated with form field name. The method returns only the first value in case that more values were posted under such name. Please note that the order in which the values are received may vary from browser to browser and should not be counted on.11.1 If no such form field or value exists then the method returns the value specified by the optional parameter default. This parameter defaults to None if not specified.

This method always returns a list of values associated with form field name. The method returns an empty list if no such form field or value exists for name. It returns a list consisting of one item if only one such value exists.

Using these methods you can write nice compact code:

import cgi
form = cgi.FieldStorage()
user = form.getfirst("user", "").upper()    # This way it's safe.
for item in form.getlist("item"):
    do_something(item)


Footnotes

Note that some recent versions of the HTML specification do state what order the field values should be supplied in, but knowing whether a request was received from a conforming browser, or even from a browser at all, is tedious and error-prone.
See About this document... for information on suggesting changes.