4.3. Composing Web Pages in Python¶
4.3.1. Dynamically Created Static Local Pages from Python¶
For the rest of this chapter, the example files will come from the www directory under the main examples directory you unzipped. I will refer to example file there as “example www files”.
As the overview indicated, dynamic web applications typically involve getting input from a web page form, processing the input in a program on the server, and displaying output to a web page. Introducing all these new ideas at once could be a lot to absorb, so this section uses familiar keyboard input into a regular Python program and then, like in the final version, processes the input and produces the final web page output.
Follow this sequence of steps:
- Open the example www file
hello.html
in your browser, to see what it looks like. - Change your browser view - for instance go back to the previous page you displayed.
- Open the same hello.html file in Kompozer, if that works for you, or another editor that will show the html source, as discussed in HTML Source Markup.
- If using Kompozer, switch to the Source view (clicking the Source tab).
Sometimes you will want to copy HTML text into a Python program.
For instance, I selected and copied the entire contents of the
hello.html
source view and pasted it into a multi-line string in the Python program shown and discussed below. - Careful, note the change from past practice here: Start Python from inside the www directory. In Windows you may start Idle with the IdleOnWindows shortcut that I placed in the www directory, not the original example directory.
- Open the www example program
helloWeb1.py
in an Idle edit window. - Run it.
You should see a familiar web page appear in your default browser (possibly not the one you have been using). This is obviously not a very necessary program, since you can select this page directly in your browser! Still, one step at a time: it illustrates several useful points. The program is copied below. Read it:
'''A simple program to create an html file froma given string,
and call the default web browser to display the file.'''
contents = '''<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>Hello</title>
</head>
<body>
Hello, World!
</body>
</html>
'''
def main():
browseLocal(contents)
def strToFile(text, filename):
"""Write a file with the given name and the given text."""
output = open(filename,"w")
output.write(text)
output.close()
def browseLocal(webpageText, filename='tempBrowseLocal.html'):
'''Start your webbrowser on a local file containing the text
with given filename.'''
import webbrowser, os.path
strToFile(webpageText, filename)
webbrowser.open("file:///" + os.path.abspath(filename)) #elaborated for Mac
main()
This program encapsulates two basic operations into the last two
functions that will be used over and over. The first,
strToFile
, has nothing new, it just puts specified text in a
file with a specified name. The second, browseLocal
, does more.
It takes specified text (presumably a web page), puts it in a file,
and directly displays the file in your default web browser. It uses the
open
function from the webbrowser
module to start the new
page in your web browser.
The open function here requires the name of a
file or URL. Since the page is automatically generated by the program
for one-time immediate viewing, it automatically uses
the same throwaway filename, tempBrowseLocal.html
specified as the default in the keyword parameter. If you
really want another specific, name you could pass it as a parameter.
In this particular program the text that goes in the file is just
copied from the literal string named contents
in the program.
This is no advance over just opening the file in the browser directly! Still, it is a start towards the aim of creating web content dynamically.
An early example in this tutorial displayed the fixed
Hello World!'
to the screen. This was later modified in
hello_you4.py
to incorporate user input using the string format
method of Dictionaries and String Formatting,
person = input('Enter your name: ')
greeting = 'Hello {person}!'.format(**locals())
print(greeting)
Similarly, I can turn the web page contents into a format string,
and insert user data. Load and run the www example program
helloWeb2.py
.
The simple changes from helloWeb1.py
are marked at the
beginning of the file and shown below. I modified the web page text
to contain ‘Hello, {person}!’ in place of ‘Hello, World!’,
making the string into a format string, which I renamed to the
more appropriate pageTemplate
. The changed initial portion with
the literal string and and the main program then becomes
pageTemplate = '''
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>Hello</title>
</head>
<body>
Hello, {person}!
</body>
</html>''' # NEW note '{person}' two lines up
def main(): # NEW
person = input("Enter a name: ")
contents = pageTemplate.format(**locals())
browseLocal(contents)
Now the line
contents = pageTemplate.format(**locals())
incorporaties the person’s name into the contents for the web page before saving it to a file and displaying it.
In this case, I stored the literal format string inside the Python program, but consider a different approach:
Load and run the www example program helloWeb3.py
. It behaves
exactly like helloWeb2.py, but is slightly different internally -
it does not directly contain the web page template string. Instead
the web page template string is read from the file
helloTemplate.html
.
Below is the beginning of helloWeb3.py, showing the only new
functions. The first, fileToStr
, will be a standard function
used in the future. It is the inverse of strToFile
.
The main program obtains the input. In this simple example, the
input is used directly, with little further processing. It is
inserted into the web page, using the file helloTemplate.html
as a format string.
def fileToStr(fileName): # NEW
"""Return a string containing the contents of the named file."""
fin = open(fileName);
contents = fin.read();
fin.close()
return contents
def main():
person = input('Enter a name: ')
contents = fileToStr('helloTemplate.html').format(**locals()) # NEW
browseLocal(contents)
Although helloTemplate.html
is not intended to be viewed by the
user (being a template), you should open it in a browser or web editor
(Kompozer or ...) to look at it. It is legal to create a web page in a web
page editor with expressions in braces embedded in it! If you look
in the source view in Kompozer or in a web source editor,
you will see something similar to
the literal string in helloWeb2.py, except the lines are broken up
differently. (This makes no difference in the formatted result,
since in html, all white space is considered the same.)
Back in the Normal mode in Kompozer, or in source mode for any html editor, add an
extra line of text right after the line “Hello, {person}!”.
Then save the file again (under the same
name). Run the program helloWeb3.py
again, and see that you
have been able to change the appearance of the output without
changing the Python program itself. That is the aim of using the
template html page, allowing the web output formatting to be
managed mostly independently from the Python program.
A more complicated but much more common situation is where the input data is processed and transformed into results somehow, and these results, often along with some of the original input, are embedded in the output web page that is produced.
As a simple example, load and run the www example program
additionWeb.py
, which uses the template file
additionTemplate.html
.
The aim in the end of this chapter is to have user input come from
a form on the web rather than the keyboard on a local machine, but
in either case the input is still transformed into results and all
embedded in a web page. To make parts easily reusable, I obtain
the input in a distinct place from where the input is
processed. In keeping with the later situation with web forms,
all input is of string type (using keyboard input
for now).
Look at the program. You will see only a few new lines! Because of the modular design, most of the program is composed of recent standard functions reused.
The only new code is at the beginning and is shown here:
def processInput(numStr1, numStr2): # NEW
'''Process input parameters and return the final page as a string.'''
num1 = int(numStr1) # transform input to output data
num2 = int(numStr2)
total = num1+num2
return fileToStr('additionTemplate.html').format(**locals())
def main(): # NEW
numStr1 = input('Enter an integer: ') # obtain input
numStr2 = input('Enter another integer: ')
contents = processInput(numStr1, numStr2) # process input into a page
browseLocal(contents) # display page
The input is obtained (via input
for now), and it is processed
into a web page string, and as a separate step it is displayed in a
local web page.
There are a few things to note:
- All input is strings. Before the numerical calculations, the digit strings must be converted to integers.
- I do calculate (a very simple!) result and use it in the output web page.
- Although it is not in the Python code, an important part of the result comes from the web page format string in additionTemplate.html, which includes the needed variable names in braces, {num1}, {num2}, and {total}. View it in your browser or in a web editor.
When you write your own code, you might modify additionWeb.py
,
or you can start from a stripped down skeleton in the example www folder,
skeletonForWeb.py
, with comments about where
to insert your special code.
We will examine the bottom part of the following diagram later. The top part outlines the flow of data from string input to web page in your browser for a regular Python program like what we have been describing, with the processing outlined in the middle line. The parts in the middle will be common to the later client/server program, that manges input and output with the bottom line, that we will discuss later.
Again, this last section was somewhat artificial. You are not in the end likely to find such programs practical as end products. However such programs are reasonable to write and test and they include almost all the code you will need for a more practical (but harder to debug) CGI program, coming next....
4.3.1.1. Quotient Web Exercise¶
* Save additionWeb.py
or skeletonForWeb.py
as quotientWeb.py
. Modify it to
display the results of a division problem in a web page.
As in the exercises in Chapter 1, display a full sentence
labeling the initial data and both the integer quotient and the remainder.
You can
take your calculations from Quotient String Return Exercise.
You should
only need to make Python changes to the processInput
and
main
functions. You will also need the HTML for the output page
displayed. Make a web page template file called
quotientTemplate.html
and read it into your program.
Turn in both quotientWeb.py
and quotientTemplate.html
.