Dynamic Web Pages
4.3. CGI DYNAMIC WEB PAGES
4.3.2. A Simple Buildup Before we get too complicated, consider the source code of a couple of
even simpler examples.
4.3.2.1. hellotxt.cgi. The simplest case is a CGI script with no input. The script just generates plain text, rather than HTML. Assuming you have your local server going, you can go to the link for hellotxt.cgi, http://localhost:8080/hellotxt.cgi. The code is in the www example directory, hellotxt.cgi, and below for you to read:
#!/usr/bin/python
# Required header that tells the browser how to render the text. print("Content-Type: text/plain\n\n") # here text -- not html
# Print a simple message to the display window. print("Hello, World!\n")
The top line is what tells a Unix server that this is a Python program. It says where to find the Python interpreter to process the rest of the script. This exact line is always required to run on a Unix server (like
the one Loyola’s Computer Science Department uses). The line is ignored in Windows. If you leave the line there as a part of your standard text, you have one less thing to think about when uploading to a Unix server.
The first print function is telling the server which receives this output, that the format of the rest of the output will be plain text. This information gets passed back to the browser later. This line should be included exactly as stated IF you only want the output to be plain text (the simplest case, but not our usual case).
The rest of the output (in this case just from one print function) becomes the body of the plain text document you see on your browser screen, verbatim since it is plain text. The server captures this output and redirects it to your browser.
4.3.2.2. hellohtml.cgi. We can make some variation and display an already determined html page rather than plain text. Try the link http://localhost:8080/hellohtml.cgi. The code is in the www example directory, hellohtml.cgi, and below for you to read:
#!/usr/bin/python
print("Content-Type: text/html\n\n") # html markup follows
print(""" <html> <Title>Hello in HTML</Title> <body> <p>Hello There!</p> <p><b>Hi There!</b></p> </body> </html> """)
There are two noteworthy changes. The first print function now declares the rest of the output will be html. This is the standard line you will be using for your CGI programs. The remaining print function has the markup for an html page. Note that the enclosing triple quotes work for a multi line string. Other than as a simple illustration, this CGI script has no utility: Just putting the contents of the last print function in a file for a static web page hello.html is much simpler.
4.3.2.3. now.cgi. One more simple step: we can have a CGI script that generates dynamic output by reading the clock from inside of Python: Try the link http://localhost:8080/now.cgi. Then click the refresh button and look again. This cannot come from a static page. The code is in the www example directory, now.cgi, and below for you to read:
#!/usr/bin/python
import time
print("Content-Type: text/html\n\n") # html markup follows
timeStr = time.strftime("%c") # obtains complete current time
htmlFormat = """ <html>
<Title>The Time Now</Title> <body>
<p>The current Central date and time is: {timeStr}</p> </body>
</html> """
print(htmlFormat.format(**locals())) # see embedded {timeStr} ^ above
This illustrates a couple more ideas: First a library module, time, is imported and used to generate the string for the current date and time.
4.3. CGI - DYNAMIC WEB PAGES 134
The web page is generated like in helloWeb2.py, embedding the dynamic data (in this case the time) into a literal web page format string. (Note the embedded {timeStr}.) Unlike helloWeb2.py, this is a CGI script so the web page contents are delivered to the server just with a print function.
4.3.2.4. adder.cgi. It is a small further step to processing dynamic input. Try filling out and submitting the adder form one more time, http://localhost:8080/adder.html. This time notice the URL at the top of the browser page when the result is displayed. You should see something like the following (only the numbers should be the ones you entered):
http://localhost:8080/adder.cgi?x=24&y=56
This shows one mechanism to deliver data from a web form to the CGI script that processes it. The names x and y are used in the form (as we will see later) and the data you entered is associated with those names. In fact a form is not needed at all to create such an association: If you directly go to the URLs http://localhost:8080/adder.cgi?x=24&y=56 or http://localhost:8080/adder.cgi?x= -12345678924&y=33333333333, you get arithmetic displayed without the form. This is just a new input mechanism into the CGI script.
You have already seen a program to produce this adder page from inside a regular Python program taking input from the keyboard. The new CGI version, adder.cgi, only needs to make a few modifications to accept input this way from the browser. New features are commented in the source and discussed below. The new parts are the import statement through the main function, and the code after the end of the fileToStr function. Read at least these new parts in the source code shown below:
#!/usr/bin/python
import cgi # NEW
def main(): # NEW except for the call to processInput
form = cgi.FieldStorage() # standard cgi script lines to here!
# use format of next two lines with YOUR names and default data
numStr1 = form.getfirst("x", "0") # get the form value associated with form # name ’x’. Use default "0" if there is none. numStr2 = form.getfirst("y", "0") # similarly for name ’y’
contents = processInput(numStr1, numStr2) # process input into a page print(contents)
def processInput(numStr1, numStr2): # from additionWeb.py
’’’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())
# the remaining code should become standard in your cgi scripts def fileToStr(fileName):
"""Return a string containing the contents of the named file.""" fin = open(fileName);
contents = fin.read(); fin.close()
return contents
try: # NEW
print("Content-type: text/html\n\n") # say generating html main()
except:
cgi.print_exception() # catch and print errors First the overall structure of the code:
• To handle the CGI input we import the cgi module.
• The main body of the code is in a main method, following good programming practice.
• After the definition of main come supporting functions, each one copied from the earlier local web page version, additionWeb.py.
At the end is the new, but standard, cgi wrapper code for main(). This is code that you can always just copy. I chose to put the initial print function here, that tells the server html is being produced. That mean the main method only needs to construct and print the actual html code. Also keep the final try-except block that catches any execution errors in the program and generates possibly helpful trace information that you can see from your browser. (Writing such error catching code in general is not covered in this introductory tutorial.)
The main function has three sections, as in the local web page version: read input (this time from the form), process it, and generate the html output.
• Reading input: The first line of main is a standard one (to copy) that sets up an object called form that holds the CGI form data accompanying the web request sent by the browser. You access the form data with statements like the next two that have the pattern:
variable = form.getfirst(nameAttrib, default)
If there is a form field with name nameAttrib, its value from the browser data is assigned to variable. If no value is given in the browser’s data for nameAttrib, variable is set equal to default instead. In this way data associated with names given by the browser can transferred to your Python CGI program. In this program the values associated with the browser-supplied names, ’x’ and ’y’, are extracted. I use Python variable names that remind you that all values from the browser forms are strings.
• The processInput function that is passed the input parameters from whatever source, is exactly the same as in additionWeb.py, so we already know it works!
• Output the page. In a CGI script this is easier than with the local web pages: just print it – no need to save and separately display a file! The server captures the “printed” output.
This program can now serve as a template for your own CGI scripts: The only things you need to change are the lines in main() that get the input from a web form, and the contents of processInput, and the processInput part can be written and tested earlier with a local web page. While this is the only Python code, you still need to create an output web page template, and refer to it in the parameter of fileToStr.