Dynamic Web Pages
4.2. Composing Web Pages in Python
The discussion of web page editing continues in Section 4.3.4, on html forms, but first we get Python into the act.
4.1.3. Editing and Testing Different Document Formats. In this chapter you will be working
with several different types of documents that you will edit and test in very different ways. The ending of their names indicate their use. Each time a new type of file is discussed in later sections, the proper ways to work with it will be repeated, but with all the variations, it is useful to group them all in one place now:
...Web.py: My convention for regular Python programs taking all their input from the keyboard,
and producing output displayed on a web page. These programs can be run like other Python programs, directly from an operating system folder or from inside Idle.
...html: Web documents most often composed in an editor like Kompozer. By my convention, these
are split into two categories
...Template.html or ...Output.html: are not intended to be displayed directly in a browser,
but instead are read by a Python program (...cgi or ...Web.py) to create a template or format string for a final web page that is dynamically generated inside the Python program.
Other: files ending in .html are intended to be directly viewed in a web browser. Except for the
simple static earlier examples in Section 4.1.2, they are designed to reside on a web server, where they can pass information to a Python CGI program. To make this work on your computer:
(1) Have all the web pages in the same directory as the example program localCGIServer.py (2) Have localCGIServer.py running, started from a directory window, not from inside Idle (3) In the browser URL field, the web page file name must be preceded by http://localhost:8080/.
For example, http://localhost:8080/adder.html would refer to the file adder.html, in the same directory as the running localCGIServer.py.
...cgi: Python CGI programs, intended to be run from a web server. It is sometimes useful to access
a CGI program directly in a browser. To run on your computer, like the Other html files above, you need to refer to a URL starting with http://localhost:8080/. For example, http://localhost:8080/now.cgi would call the file now.cgi, which must be in the same directory as the running localCGIServer.py. More often CGI programs are referenced in a web form, and the program is called indirectly by the web server. CGI programs can be edited and saved inside Idle, but they do not run properly from inside Idle.
4.2. Composing Web Pages in Python
4.2.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 in 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 treats only the last part, output to the web, and uses familiar keyboard input into a regular Python program.
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.
In 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 start the Idle shortcut link 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 from a 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, ’helloPython.html’)
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):
"""Start your webbrowser on a local file containing the text.""" strToFile(webpageText, filename)
import webbrowser
webbrowser.open(filename)
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 web browser. It uses the open function from the webbrowser module to start the new page in your web browser.
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 Section 1.12.2,
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
4.2. COMPOSING WEB PAGES IN PYTHON 130
<!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():
person = input(’Enter a name: ’) # NEW
contents = pageTemplate.format(**locals()) # NEW
browseLocal(contents, ’helloPython2.html’) # NEW filename
incorporating the person’s name into the contents for the web page before saving 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 ’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, ’helloPython3.html’) # NEW filename
Although helloTemplate.html is not intended to be viewed by the user (being a template), you should open it in a web editor (like Kompozer) 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 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, a newline is treated the same way as a space.)
Back in the Normal mode, add some formatting like italics, and an extra line of text, and 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 trans- formed into results somehow, and these results, often along with some of the original input, are embedded in the 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, ’helloPython3.html’) # 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 for- mat string in additionTemplate.html, which includes the needed variable names in braces, {num1}, {num2}, and {total}.
Exercise 4.2.1.1. ** Save additionWeb.py as quotientWeb.py. Modify it to display the results of a division problem in a web page. You can take your calculations from Exercise 1.10.3.2. You should only need to make Python changes to the processInput and main functions. You will also need the HTML for the page displayed. Make a web page template file called quotientTemplate.html and read it into your program. In this version generated by a regular Python program, the web page is just a file generated by the program, and then the file gets displayed in the browser. When you call browseLocal, you must supply a filename for the file to be created, but the name is totally arbitrary.