20.2. cgi — Common Gateway Interface support¶
Source code: Lib/cgi.py
Support module for Common Gateway Interface (CGI) scripts.
This module defines a number of utilities for use by CGI scripts written in Python.
20.2.1. Introduction¶
A CGI script is invoked by an HTTP server, usually to process user input
submitted through an HTML <FORM> or <ISINDEX> element.
Most often, CGI scripts live in the server’s special cgi-bin directory.
The HTTP server places all sorts of information about the request (such as the
client’s hostname, the requested URL, the query string, and lots of other
goodies) in the script’s shell environment, executes the script, and sends the
script’s output back to the client.
The script’s input is connected to the client too, and sometimes the form data is read this way; at other times the form data is passed via the “query string” part of the URL. This module is intended to take care of the different cases and provide a simpler interface to the Python script. It also provides a number of utilities that help in debugging scripts, and the latest addition is support for file uploads from a form (if your browser supports it).
The output of a CGI script should consist of two sections, separated by a blank line. The first section contains a number of headers, telling the client what kind of data is following. Python code to generate a minimal header section looks like this:
print "Content-Type: text/html" # HTML is following
print # blank line, end of headers
The second section is usually HTML, which allows the client software to display nicely formatted text with header, in-line images, etc. Here’s Python code that prints a simple piece of HTML:
print "<TITLE>CGI script output</TITLE>"
print "<H1>This is my first CGI script</H1>"
print "Hello, world!"
20.2.2. Using the cgi module¶
Begin by writing import cgi. Do not use from cgi import * — the
module defines all sorts of names for its own use or for backward compatibility
that you don’t want in your namespace.
When you write a new script, consider adding these lines:
import cgitb
cgitb.enable()
This activates a special exception handler that will display detailed reports in the Web browser if any errors occur. If you’d rather not show the guts of your program to users of your script, you can have the reports saved to files instead, with code like this:
import cgitb
cgitb.enable(display=0, logdir="/path/to/logdir")
It’s very helpful to use this feature during script development. The reports
produced by cgitb provide information that can save you a lot of time in
tracking down bugs. You can always remove the cgitb line later when you
have tested your script and are confident that it works correctly.
To get at submitted form data, it’s best to use the FieldStorage class.
The other classes defined in this module are provided mostly for backward
compatibility. Instantiate it exactly once, without arguments. This reads the
form contents from standard input or the environment (depending on the value of
various environment variables set according to the CGI standard). Since it may
consume standard input, it should be instantiated only once.
The FieldStorage instance can be indexed like a Python dictionary.
It allows membership testing with the in operator, and also supports
the standard dictionary method keys() and the built-in function
len(). Form fields containing empty strings are ignored and do not appear
in the dictionary; to keep such values, provide a true value for the optional
keep_blank_values keyword parameter when creating the FieldStorage
instance.
For instance, the following code (which assumes that the
Content-Type header and blank line have already been printed)
checks that the fields name and addr are both set to a non-empty
string:
form = cgi.FieldStorage()
if "name" not in form or "addr" not in form:
print "<H1>Error</H1>"
print "Please fill in the name and addr fields."
return
print "<p>name:", form["name"].value
print "<p>addr:", form["addr"].value
...further form processing here...
Here the fields, accessed through form[key], are themselves instances of
FieldStorage (or MiniFieldStorage, depending on the form
encoding). The value attribute of the instance yields
the string value of the field. The getvalue() method
returns this string value directly; it also accepts an optional second argument
as a default to return if the requested key is not present.
If the submitted form data contains more than one field with the same name, the
object retrieved by form[key] is not a FieldStorage or
MiniFieldStorage instance but a list of such instances. Similarly, in
this situation, form.getvalue(key) would return a list of strings. If you
expect this possibility (when your HTML form contains multiple fields with the
same name), use the getlist() method, which always returns
a list of values (so that you do not need to special-case the single item
case). For example, this code concatenates any number of username fields,
separated by commas:
value = form.getlist("username")
usernames = ",".join(value)
If a field represents an uploaded file, accessing the value via the
value attribute or the getvalue()
method reads the entire file in memory as a string. This may not be what you
want. You can test for an uploaded file by testing either the
filename attribute or the file
attribute. You can then read the data at leisure from the file
attribute:
fileitem = form["userfile"]
if fileitem.file:
# It's an uploaded file; count lines
linecount = 0
while 1:
line = fileitem.file.readline()
if not line: break
linecount = linecount + 1
If an error is encountered when obtaining the contents of an uploaded file
(for example, when the user interrupts the form submission by clicking on
a Back or Cancel button) the done attribute of the
object for the field will be set to the value -1.
The file upload draft standard entertains the possibility of uploading multiple
files from one field (using a recursive multipart/* encoding).
When this occurs, the item will be a dictionary-like FieldStorage item.
This can be determined by testing its type attribute, which should be
multipart/form-data (or perhaps another MIME type matching
multipart/*). In this case, it can be iterated over recursively
just like the top-level form object.
When a form is submitted in the “old” format (as the query string or as a single
data part of type application/x-www-form-urlencoded), the items will
actually be instances of the class MiniFieldStorage. In this case, the
list, file, and filename attributes are always None.
A form submitted via POST that also has a query string will contain both
FieldStorage and MiniFieldStorage items.
20.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 upper() 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.
-
FieldStorage.getfirst(name[, default])¶ 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. 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
Noneif not specified.
-
FieldStorage.getlist(name)¶ 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)
