GUI interfaces are
easier to use than command lines and are often all we need
to simplify access to data. By making our database available on the Web,
though, we can open it up to even wider use. Anyone with Internet access
and a web browser can access the data, regardless of where they are
located and which machine they are using. Anything from workstations to
cell phones will suffice. Moreover, web-based interfaces require only a
web browser; there is no need to install Python to access the data except
on the single-server machine. Although traditional web-based approaches
may sacrifice some of the utility and speed of in-process GUI toolkits,
their portability gain can be
compelling
.
As we’ll also see later in this book, there are a variety of ways to
go about scripting interactive web pages of the sort we’ll need in order
to access our data. Basic server-side CGI scripting is more than adequate
for simple tasks like ours. Because it’s perhaps the simplest approach,
and embodies the foundations of more advanced techniques, CGI scripting is
also well-suited to getting started on the Web.
For more
advanced applications, a wealth of toolkits and frameworks
for Python—including Django, TurboGears, Google’s App Engine, pylons,
web2py, Zope, Plone, Twisted, CherryPy, Webware, mod_python, PSP, and
Quixote—can simplify common tasks and provide tools that we might
otherwise need to code from scratch in the CGI world. Though they pose a
new set of tradeoffs, emerging technologies such as Flex, Silverlight, and
pyjamas (an AJAX-based port of the Google Web Toolkit to Python, and
Python-to-JavaScript compiler) offer additional paths to achieving
interactive or dynamic user-interfaces in web pages on clients, and open
the door to using Python in Rich Internet Applications (RIAs).
I’ll say more about these tools later. For now, let’s keep things
simple and code a CGI script.
CGI scripting in
Python is easy as long as you already have a handle on
things like HTML forms, URLs, and the client/server model of the Web
(all topics we’ll address in detail later in this book). Whether you’re
aware of all the underlying details or not, the basic interaction model
is probably familiar.
In a nutshell, a user visits a website and receives a form, coded
in HTML, to be filled out in his or her browser. After submitting the
form, a script, identified within either the form or the address used to
contact the server, is run on the server and produces another HTML page
as a reply. Along the way, data typically passes through three programs:
from the client browser, to the web server, to the CGI script, and back
again to the browser. This is a natural model for the database access
interaction we’re
after—
users can
submit a database key to the server and receive the corresponding record
as a reply page.
We’ll go into CGI basics in depth later in this book, but as a
first example, let’s start out with a simple interactive example that
requests and then echoes back a user’s name in a web browser. The first
page in this interaction is just an input form produced by the HTML file
shown in
Example 1-30
. This HTML
file is stored on the web server machine, and it is transferred to the
web browser running on the client machine upon request.
Example 1-30. PP4E\Preview\cgi101.html
Read Programming Python (9 page) Page 9 Read Book Online,Top Vampire Books Read Online Free
Notice how this HTML form names the script that will process its
input on the server in itsaction
attribute. This page is requested by submitting its URL (web address).
When received by the web browser on the client, the input form that this
code produces is shown in
Figure 1-10
(in Internet Explorer here).
Figure 1-10. cgi101.html input form page
When this input form is submitted, a web server intercepts the
request (more on the web server in a moment) and runs the Python CGI
script in
Example 1-31
. Like the
HTML file, this Python script resides on the same machine as the web
server; it’s run on the server machine to handle the inputs and generate
a reply to the browser on the client. It uses thecgi
module to parse the form’s input and
insert it into the HTML reply stream, properly escaped. Thecgi
module gives us a dictionary-like
interface to form inputs sent by the browser, and the HTML code that
this script prints winds up rendering the next page on the client’s
browser. In the CGI world, the standard output stream is connected to
the client through a socket.
Example 1-31. PP4E\Preview\cgi-bin\cgi101.py
#!/usr/bin/python
import cgi
form = cgi.FieldStorage() # parse form data
print('Content-type: text/html\n') # hdr plus blank line
print('Read Programming Python (9 page) Page 9 Read Book Online,Top Vampire Books Read Online Free ') # html reply page
if not 'user' in form:
print('Who are you?')
else:
print('Hello %s!' % cgi.escape(form['user'].value))
And if all goes well, we receive the reply page shown in
Figure 1-11
—essentially, just
an echo of the data we entered in the input page. The page in this
figure is produced by the HTML printed by the Python CGI script running
on the server. Along the way, the user’s name was transferred from a
client to a server and back again—potentially across networks and miles.
This isn’t much of a website, of course, but the basic principles here
apply, whether you’re just echoing inputs or doing full-blown
e-whatever.
Figure 1-11. cgi101.py script reply page for input form
If you have trouble getting this interaction to run on Unix-like
systems, you may need to modify the path to your Python in the#!
line at the top of the script file and make
it executable with achmod
command, but
this is dependent on your web server (again, more on the missing server
piece in a moment).
Also note that the CGI script in
Example 1-31
isn’t printing complete
HTML: the
and
tags of the static HTML file in
Example 1-30
are missing.
Strictly speaking, such tags should be printed, but web browsers don’t
mind the omissions, and this book’s goal is not to teach legalistic
HTML; see other resources for more on HTML.
Before moving on, it’s worth taking a moment to compare this
basic CGI example with the simple GUI of
Example 1-28
and
Figure 1-6
. Here, we’re running scripts
on a server to generate HTML that is rendered in a web browser. In the
GUI, we make calls to build the display and respond to events within a
single process and on a single machine. The GUI runs multiple layers
of software, but not multiple programs. By contrast, the CGI approach
is much more distributed—the server, the browser, and possibly the CGI
script itself run as separate programs that usually communicate over a
network.
Because of such differences, the standalone GUI model may be
simpler and more direct: there is no intermediate server, replies do
not require invoking a new program, no HTML needs to be generated, and
the full power of a GUI toolkit is at our disposal. On the other hand,
a web-based interface can be viewed in any browser on any computer and
only requires Python on the server machine.
And just to muddle the waters further, a GUI can also employ
Python’s standard library networking tools to fetch and display data
from a remote server (that’s how web browsers do their work
internally), and some newer frameworks such as Flex, Silverlight, and
pyjamas provide toolkits that support more full-featured user
interfaces within web pages on the client (the RIAs I mentioned
earlier), albeit at some added cost in code complexity and software
stack depth. We’ll revisit the trade-offs of the GUI and CGI schemes
later in this book, because it’s a major design choice today. First,
let’s preview a handful of pragmatic issues related to CGI work before
we apply it to our people
database.
Of course, to run
CGI scripts at all, we need a web server that will serve
up our HTML and launch our Python scripts on request. The server is a
required mediator between the browser and the CGI script. If you don’t
have an account on a machine that has such a server available, you’ll
want to run one of your own. We could configure and run a full
production-level web server such as the open source Apache system
(which, by the way, can be tailored with Python-specific support by themod_python
extension). For this
chapter, however, I instead wrote a simple web server in Python using
the code in
Example 1-32
.
We’ll revisit the tools used in this example later in this book.
In short, because Python provides precoded support for various types of
network servers, we can build a
CGI-capable
and portable HTTP web server
in just 8 lines of code (and a whopping 16 if we include comments and
blank lines).
As we’ll see later in this book, it’s also easy to build
proprietary network servers with low-level socket calls in Python, but
the standard library provides canned implementations for many common
server types, web based or otherwise. Thesocketserver
module,
for instance, supports threaded and forking versions of
TCP and UDP servers. Third-party systems such as Twisted provide even
more implementations. For serving up web content, the standard library
modules used in
Example 1-32
provide what
we need
.
Example 1-32. PP4E\Preview\webserver.py
"""
Implement an HTTP web server in Python that knows how to run server-side
CGI scripts coded in Python; serves files and scripts from current working
dir; Python scripts must be stored in webdir\cgi-bin or webdir\htbin;
"""
import os, sys
from http.server import HTTPServer, CGIHTTPRequestHandler
webdir = '.' # where your html files and cgi-bin script directory live
port = 80 # default http://localhost/, else use http://localhost:xxxx/
os.chdir(webdir) # run in HTML root dir
srvraddr = ("", port) # my hostname, portnumber
srvrobj = HTTPServer(srvraddr, CGIHTTPRequestHandler)
srvrobj.serve_forever() # run as perpetual daemon
The classes this script uses assume that the HTML files to be
served up reside in the current working directory and that the CGI
scripts to be run live in a
cgi-bin
or
htbin
subdirectory there. We’re using a
cgi-bin
subdirectory for scripts, as suggested by
the filename of
Example 1-31
.
Some web servers look at filename extensions to detect CGI scripts; our
script uses this subdirectory-based scheme instead.
To launch the server, simply run this script (in a console window,
by an icon click, or otherwise); it runs perpetually, waiting for
requests to be submitted from browsers and other clients. The server
listens for requests on the machine on which it runs and on the standard
HTTP port number 80. To use this script to serve up other websites,
either launch it from the directory that contains your HTML files and a
cgi-bin
subdirectory that contains your CGI
scripts, or change itswebdir
variable to reflect the site’s root directory (it will automatically
change to that directory and serve files located there).
But where in cyberspace do you actually run the server script? If
you look closely enough, you’ll notice that the server name in the
addresses of the prior section’s examples (near the top right of the
browser after the
http://
) is always
localhost
. To keep this simple, I am running the
web server on the same machine as the web browser; that’s what the
server name “localhost” (and the equivalent IP address “127.0.0.1”)
means. That is, the client and server machines are the same: the client
(web browser) and server (web server) are just different processes
running at the same time on the same computer.
Though not meant for enterprise-level work, this turns out to be a
great way to test CGI scripts—you can develop them on the same machine
without having to transfer code back to a remote server machine after
each change. Simply run this script from the directory that contains
both your HTML files and a
cgi-bin
subdirectory for
scripts and then use
http://localhost/
…
in your
browser to access your HTML and script files. Here is the trace output
the web server script produces in a Windows console window that is
running on the same machine as the web browser and launched from the
directory where the HTML files reside:
...\PP4E\Preview>python webserver.py
mark-VAIO - - [28/Jan/2010 18:34:01] "GET /cgi101.html HTTP/1.1" 200 -
mark-VAIO - - [28/Jan/2010 18:34:12] "POST /cgi-bin/cgi101.py HTTP/1.1" 200 -
mark-VAIO - - [28/Jan/2010 18:34:12] command: C:\Python31\python.exe -u C:\Users
\mark\Stuff\Books\4E\PP4E\dev\Examples\PP4E\Preview\cgi-bin\cgi101.py ""
mark-VAIO - - [28/Jan/2010 18:34:13] CGI script exited OK
mark-VAIO - - [28/Jan/2010 18:35:25] "GET /cgi-bin/cgi101.py?user=Sue+Smith HTTP
/1.1" 200 -
mark-VAIO - - [28/Jan/2010 18:35:25] command: C:\Python31\python.exe -u C:\Users
\mark\Stuff\Books\4E\PP4E\dev\Examples\PP4E\Preview\cgi-bin\cgi101.py
mark-VAIO - - [28/Jan/2010 18:35:26] CGI script exited OK
One pragmatic note here: you may need administrator privileges in
order to run a server on the script’s default port 80 on some platforms:
either find out how to run this way or try running on a different port.
To run this server on a different port, change the port number in the
script and name it explicitly in the URL (e.g.,
http://localhost:8888/
). We’ll learn more about
this convention later in this book.
And to run this server on a remote computer, upload the HTML files
and CGI scripts subdirectory to the remote computer, launch the server
script on that machine, and replace “localhost” in the URLs with the
domain name or IP address of your server machine (e.g.,
http://www.myserver.com/
). When running the server
remotely, all the interaction will be as shown here, but inputs and
replies will be automatically shipped across network connections, not
routed between programs running on the same
computer
.
To delve further into the server classes our web server script
employs, see their implementation in Python’s standard library
(
C:\Python31\Lib
for Python 3.1);
one of the major advantages of open source system like Python is that we
can always look under the hood this way. In
Chapter 15
, we’ll expand
Example 1-32
to allow the directory
name and port numbers to be passed in on the command
line.