Read Programming Python Online

Authors: Mark Lutz

Tags: #COMPUTERS / Programming Languages / Python

Programming Python (152 page)

BOOK: Programming Python
3.44Mb size Format: txt, pdf, ePub
ads
Adding Pictures and Generating Tables

Let’s get back
to writing server-side code. As anyone who’s ever surfed
the Web knows, web pages usually consist of more than simple text.
Example 15-4
is a Python CGI script
that prints an

HTML tag
in its output to produce a graphic image in the client browser. This
example isn’t very Python-specific, but note that just as for simple
HTML files, the image file (
ppsmall.gif
, one level
up from the script file) lives on and is downloaded from the server
machine when the browser interprets the output of this script to render
the reply page (even if the server’s machine is the same as the
client’s).

Example 15-4. PP4E\Internet\Web\cgi-bin\tutor1.py

#!/usr/bin/python
text = """Content-type: text/html
CGI 101

A Second CGI Script




Hello, CGI World!


[image]


"""
print(text)

Notice the use of the triple-quoted string block here; the entire
HTML string is sent to the browser in one fell swoop, with the
print
call statement at the end. Be sure that
the blank line between the Content-type header and the first HTML is
truly blank in the string (it may fail in some browsers if you have any
spaces or tabs on that line). If both client and server are functional,
a page that looks like
Figure 15-4
will be generated
when this script is referenced and run.

So far, our CGI scripts have been putting out canned HTML that
could have just as easily been stored in an HTML file. But because CGI
scripts are executable programs, they can also be used to generate HTML
on the fly, dynamically—even, possibly, in response to a particular set
of user inputs sent to the script. That’s the whole purpose of CGI
scripts, after all. Let’s start using this to better advantage now, and
write a Python script that builds up response HTML programmatically,
listed in
Example 15-5
.

Figure 15-4. A page with an image generated by tutor1.py

Example 15-5. PP4E\Internet\Web\cgi-bin\tutor2.py

#!/usr/bin/python
print("""Content-type: text/html
CGI 101

A Third CGI Script




Hello, CGI World!



""")
for i in range(5):
print('')
for j in range(4):
print('' % (i, j))
print('')
print("""
%d.%d



""")

Despite all the tags, this really is Python code—the
tutor2.py
script uses triple-quoted strings to
embed blocks of HTML again. But this time, the script also uses nested
Python
for
loops to dynamically
generate part of the HTML that is sent to the browser. Specifically, it
emits HTML to lay out a two-dimensional table in the middle of a page,
as shown in
Figure 15-5
.

Figure 15-5. A page with a table generated by tutor2.py

Each row in the table displays a “row.column” pair, as generated
by the executing Python script. If you’re curious how the generated HTML
looks, select your browser’s View Source option after you’ve accessed
this page. It’s a single HTML page composed of the HTML generated by the
first
print
in the script, then the
for
loops, and finally the last
print
. In other words, the
concatenation of this script’s output is an HTML document with
headers.

Table tags

The script
in
Example 15-5
generates HTML table tags. Again, we’re not out to learn HTML here,
but we’ll take a quick look just so that you can make sense of this
book’s examples. Tables are declared by the text between


and

tags in HTML. Typically, a
table’s text in turn declares the contents of each table row between

and

tags and each column within a
row between

and

tags. The loops in our script
build up HTML to declare five rows of four columns each by printing
the appropriate tags, with the current row and column number as column
values.

For instance, here is part of the script’s output, defining the
first two rows (to see the full output, run the script standalone from
a system command line, or select your browser’s View Source
option):














. . .
0.00.10.20.3
1.01.11.21.3

Other table tags and options let us specify a row title
(

), lay out borders, and
so on. We’ll use more table syntax to lay out forms in a uniform
fashion later in
this tutorial.

Adding User Interaction

CGI scripts are
great at generating HTML on the fly like this, but they
are also commonly used to implement interaction with a user typing at a
web browser. As described earlier in this chapter, web interactions
usually involve a two-step process and two distinct web pages: you fill
out an input form page and press Submit, and a reply page eventually
comes back. In between, a CGI script processes the form input.

Submission page

That description
sounds simple enough, but the process of collecting user
inputs requires an understanding of a special HTML tag,


. Let’s look at the
implementation of a simple web interaction to see forms at work.
First, we need to define a form page for the user to fill out, as
shown in
Example 15-6
.

Example 15-6. PP4E\Internet\Web\tutor3.html


CGI 101

A first user interaction: forms





Enter your name:





tutor3.html
is a simple HTML file, not a
CGI script (though its contents could be printed from a script as
well). When this file is accessed, all the text between its


and

tags generates the input
fields and Submit button shown in
Figure 15-6
.

Figure 15-6. A simple form page generated by tutor3.html

More on form tags

We won’t go into all the
details behind coding HTML forms, but a few highlights
are worth underscoring. The following occurs within a form’s HTML
code:

Form handler action

The
form’s
action
option gives the URL of a CGI script that will be invoked to
process submitted form data. This is the link from a form to its
handler
program—
in this
case, a program called
tutor3.py
in the
cgi-bin
subdirectory of the locally running
server’s working directory. The
action
option is the equivalent of
command
options in tkinter buttons—it’s where a callback handler (here,
a remote handler script) is registered to the browser and
server.

Input fields

Input controls are
specified with nested

tags. In this example,
input tags have two key options. The
type
option accepts values such as
text
for text fields and
submit
for a Submit button
(which sends data to the server and is labeled “Submit Query” by
default). The
name
option is the hook
used to identify the entered value by key, once all the form
data reaches the server. For instance, the server-side CGI
script we’ll see in a moment uses the string
user
as a key to get the data typed
into this form’s text field.

As we’ll see in later examples, other input tag options
can specify initial values (
value=X
), display-only mode (
readonly
), and so on. As we’ll also
see later, other input
type
option
values may transmit hidden data that embeds state information in
pages (
type=hidden
),
reinitializes fields (
type=reset
), or makes multiple-choice
buttons (
type=checkbox
).

Submission method:
get
and
post

Forms also
include a
method
option to specify the encoding
style to be used to send data over a socket to the target server
machine. Here, we use the
post
style, which contacts the server
and then ships it a stream of user input data in a separate
transmission over the socket.

An alternative
get
style ships input information to the server in a single
transmission step by appending user inputs to the query string
at the end of the URL used to invoke the script, usually after a
?
character. Query parameters
were introduced earlier when we met URLs; we will put them to
use later in this section.

With
get
, inputs
typically show up on the server in environment variables or as
arguments in the command line used to start the script. With
post
, they must be read from
standard input and decoded. Because the
get
method appends inputs to URLs, it
allows users to bookmark actions with parameters for later
submission (e.g., a link to a retail site, together with the
name of a particular item);
post
is very generally meant for
sending data that is to be submitted once (e.g., comment
text).

The
get
method is
usually considered more efficient, but it may be subject to
length limits in the operating system and is less secure
(parameters may be recorded in server logs, for instance).
post
can handle larger inputs
and may be more secure in some scenarios, but it requires an
extra transmission. Luckily, Python’s
cgi
module transparently handles
either encoding style, so our CGI scripts don’t normally need to
know or care which is used.

Notice that the
action
URL in
this example’s form spells out the full address for illustration.
Because the browser remembers where the enclosing HTML page came from,
it works the same with just the script’s filename, as shown in
Example 15-7
.

Example 15-7. PP4E\Internet\Web\tutor3-minimal.html


CGI 101

A first user interaction: forms





Enter your name:





It may help to remember that URLs embedded in form action tags
and hyperlinks are directions to the browser first, not to the script.
The
tutor3.py
script itself doesn’t care which
URL form is used to trigger it—minimal or complete. In fact, all parts
of a URL through the script filename (and up to URL query parameters)
are used in the conversation between browser and HTTP server, before a
CGI script is ever spawned. As long as the browser knows which server
to contact, the URL will work.

On the other hand, URLs submitted outside of a page (e.g., typed
into a browser’s address field or sent to the Python
urllib.request
module we’ll revisit later)
usually must be completely specified, because there is no notion of a
prior page.

Response script

So far, we’ve
created only a static page with an input field. But the
Submit button on this page is loaded to work magic. When pressed, it
triggers the possibly remote program whose URL is listed in the form’s
action
option, and passes this
program the input data typed by the user, according to the form’s
method
encoding style option. On
the server, a Python script is started to handle the form’s input data
while the user waits for a reply on the client; that script is shown
in
Example 15-8
.

Example 15-8. PP4E\Internet\Web\cgi-bin\tutor3.py

#!/usr/bin/python
"""
runs on the server, reads form input, prints HTML;
url=http://server-name/cgi-bin/tutor3.py
"""
import cgi
form = cgi.FieldStorage() # parse form data
print('Content-type: text/html') # plus blank line
html = """
tutor3.py

Greetings




%s



"""
if not 'user' in form:
print(html % 'Who are you?')
else:
print(html % ('Hello, %s.' % form['user'].value))

As before, this Python CGI script prints HTML to generate a
response page in the client’s browser. But this script does a bit
more: it also uses the standard
cgi
module to parse the input data entered by the user on the prior web
page (see
Figure 15-6
).

Luckily, this is automatic in Python: a call to the standard
library
cgi
module’s
FieldStorage
class
does all the work of extracting form data from the input stream and
environment variables, regardless of how that data was passed—in a
post
style stream or in
get
style parameters appended to the URL.
Inputs sent in both styles look the same to Python scripts.

Scripts should call
cgi.FieldStorage
only once and before
accessing any field values. When it is called, we get back an object
that looks like a dictionary—user input fields from the form (or URL)
show up as values of keys in this object. For example, in the script,
form['user']
is an object whose
value
attribute is a string
containing the text typed into the form’s text field. If you flip back
to the form page’s HTML, you’ll notice that the input field’s
name
option was
user
—the name in the form’s HTML has become
a key we use to fetch the input’s value from a dictionary. The object
returned by
FieldStorage
supports
other dictionary operations, too—for instance, the
in
expression may be used to check whether a
field is present in the input data.

Before exiting, this script prints HTML to produce a result page
that echoes back what the user typed into the form. Two
string-formatting expressions (
%
)
are used to insert the input text into a reply string, and the reply
string into the triple-quoted HTML string block. The body of the
script’s output looks like this:

tutor3.py

Greetings




Hello, King Arthur.




In a browser, the output is rendered into a page like the one in
Figure 15-7
.

Figure 15-7. tutor3.py result for parameters in a form

Passing parameters in URLs

Notice that the URL
address of the script that generated this page shows up
at the top of the browser. We didn’t type this URL itself—it came from
the
action
tag of the prior page’s
form
HTML. However, nothing is
stopping us from typing the script’s URL explicitly in our browser’s
address field to invoke the script, just as we did for our earlier CGI
script and HTML file examples.

But there’s a catch here: where does the input field’s value
come from if there is no form page? That is, if we type the CGI
script’s URL ourselves, how does the input field get filled in?
Earlier, when we talked about URL formats, I mentioned that the
get
encoding scheme tacks input
parameters onto the end of URLs. When we type script addresses
explicitly, we can also append input values on the end of URLs, where
they serve the same purpose as

fields in forms. Moreover, the
Python
cgi
module makes URL and
form inputs look identical to scripts.

For instance, we can skip filling out the input form page
completely and directly invoke our
tutor3.py
script by visiting a URL of this form (type this in your browser’s
address field):

http://localhost/cgi-bin/tutor3.py?user=Brian

In this URL, a value for the input named
user
is specified explicitly, as if the user
had filled out the input page. When called this way, the only
constraint is that the parameter name
user
must match the name expected by the
script (and hardcoded in the form’s HTML). We use just one parameter
here, but in general, URL parameters are typically introduced with a
?
and are followed by one or more
name=value
assignments, separated
by
&
characters if there is
more than one.
Figure 15-8
shows the
response page we get after typing a URL with explicit inputs.

Figure 15-8. tutor3.py result for parameters in a URL

In fact, HTML forms that specify the
get
encoding style also cause inputs to be
added to URLs this way. Try changing
Example 15-6
to use
method=GET
, and submit the
form—
the name input in the form shows up
as a query parameter in the reply page address field, just like the
URL we manually entered in
Figure 15-8
. Forms can use
the
post
or
get
style. Manually typed URLs with
parameters use
get
.

Generally, any CGI script can be invoked either by filling out
and submitting a form page or by passing inputs at the end of a URL.
Although hand-coding parameters in URLs can become difficult for
scripts that expect many complex parameters, other programs can
automate the construction process.

When CGI scripts are invoked with explicit input parameters this
way, it’s not too difficult to see their similarity to
functions
, albeit ones that live
remotely on the Net. Passing data to scripts in URLs is similar to
keyword arguments in Python functions, both operationally and
syntactically. In fact, some advanced web frameworks such as Zope make
the relationship between URLs and Python function calls even more
literal: URLs become more direct calls to Python functions.

Incidentally, if you clear out the name input field in the form
input page (i.e., make it empty) and press Submit, the
user
name field becomes empty. More
accurately, the browser may not send this field along with the form
data at all, even though it is listed in the form layout HTML. The CGI
script detects such a missing field with the dictionary
in
expression and produces the page captured
in
Figure 15-9
in
response.

Figure 15-9. An empty name field producing an error page

In general, CGI scripts must check to see whether any inputs are
missing, partly because they might not be typed by a user in the form,
but also because there may be no form at all—input fields might not be
tacked onto the end of an explicitly typed or constructed
get
-style URL. For instance, if we type the
script’s URL without any parameters at all—by omitting the text from
the
?
and beyond, and visiting
http://localhost/cgi-bin/tutor3.py
with an
explicitly entered URL—we get this same error response page. Since we
can invoke any CGI through a form or URL, scripts must anticipate both
scenarios.

BOOK: Programming Python
3.44Mb size Format: txt, pdf, ePub
ads

Other books

Eden's Garden by Juliet Greenwood
The Bleeding Sun by Abhishek Roy
An Uncommon Grace by Serena B. Miller
Sons of the Wolf by Barbara Michaels
Wild Cards [07] Dead Man's Hand by George R.R. Martin
Hot Wheels by William Arden
Breach (The Blood Bargain) by Reeves, Macaela
A Belated Bride by Karen Hawkins
Beyond the Grave by C. J. Archer
Diners, Dives & Dead Ends by Austin, Terri L.