Except for automated tools, though, typing such a long URL will be noticeably more
difficult than filling out the input page. Here is part of the reply page generated for the
“guido” record’s display of Figure 1-18 (use your browser’s “view page source” option
to see this for yourself). Note how the < and > characters are translated to HTML escapes
with cgi.escape before being inserted into the reply:
<tr><th>key<td><input type=text name=key value="guido">
<tr><th>name<td><input type=text name=name value="'GvR'">
<tr><th>age<td><input type=text name=age value="None">
<tr><th>job<td><input type=text name=job value="'BDFL'">
<tr><th>pay<td><input type=text name=pay value="'<shrubbery>'">
As usual, the standard library urllib module package comes in handy for testing our
CGI script; the output we get back is raw HTML, but we can parse it with other standard
library tools and use it as the basis of a server-side script regression testing system run
on any Internet-capable machine. We might even parse the server’s reply fetched this
way and display its data in a client-side GUI coded with tkinter; GUIs and web pages
are not mutually exclusive techniques. The last test in the following interaction shows
a portion of the error message page’s HTML that is produced when the action is missing
or invalid in the inputs, with line breaks added for readability:
>>> from urllib.request import urlopen
>>> url = 'http://localhost/cgi-bin/peoplecgi.py?action=Fetch&key=sue'
>>> urlopen(url).read()
b'<html>\n<title>People Input Form</title>\n<body>\n
<form method=POST action="peoplecgi.py">\n <table>\n
<tr><th>key<td><input type=text name=key value="sue">\n
<tr><th>name<td><input type=text name=name value="\'Sue Smith\'">\n
<tr><t ...more deleted...
>>> urlopen('http://localhost/cgi-bin/peoplecgi.py').read()
b'<html>\n<title>People Input Form</title>\n<body>\n
<form method=POST action="peoplecgi.py">\n <table>\n
<tr><th>key<td><input type=text name=key value="Missing or invalid action!">\n
<tr><th>name<td><input type=text name=name value="\'?\'">\n
<tr><th>age<td><input type=text name=age value="\'?\'">\n<tr> ...more deleted...
In fact, if you’re running this CGI script on “localhost,” you can use both the last
section’s GUI and this section’s web interface to view the same physical shelve file—
these are just alternative interfaces to the same persistent Python objects. For compar-
ison, Figure 1-19 shows what the record we saw in Figure 1-18 looks like in the GUI;
it’s the same object, but we are not contacting an intermediate server, starting other
scripts, or generating HTML to view it.
And as before, we can always check our work on the server machine either interactively
or by running scripts. We may be viewing a database through web browsers and GUIs,
but, ultimately, it is just Python objects in a Python shelve file:
>>> import shelve
>>> db = shelve.open('class-shelve')
>>> db['sue'].name
'Sue Smith'
Step 6: Adding a Web Interface | 67