Python & CGI Programming


Python Module Flow

The following module diagram shows how the Python CGI modules and the HTML templates work together.

Python Module Flow

First, we start the process by clicking on an HTML link. I was pleasantly surprised when I realized that the href in a link could point to a CGI module as well as an HTML page.

From the W3C website:

A link has two ends -- called anchors -- and a direction. The link starts at the "source" anchor and points to the "destination" anchor, which may be any Web resource (e.g., an image, a video clip, a sound bite, a program, an HTML document, an element within an HTML document, etc.).

Here's an example of what I mean.

<a href="CGI/ProcessSetup.cgi">Process</a>

Clicking the link causes the ProcessSetup.cgi module to execute. (My website host required that Python executable modules end in .cgi. Your website host may allow .py extensions.) At a minimum, this module will


# Inline code to process template

print "Content-Type: text/html"
print

sys.stderr  = sys.stdout

for text in open("../author_feedback.html").xreadlines():

    text = HTTPText(text)
    
    # Make HTML substitutions
 
    text = StringReplace (text, '<<author>>', author)
    text = StringReplace (text, '<<story>>', story_text)
 
    text = ValueReplace (text, '<<author_id>>', str(author_id))
    text = ValueReplace (text, '<<story_id>>', str(story_id))
    
    print text

The relative link in the xreadlines statement has the '../' in front because the CGI directory from which this module is executed is the child directory of the HTML template library. (Again, this may vary with different website hosts.)

The HTTPText module removes all of the line feed / carriage control characters from the HTML template because when the module writes a line to the HTML page, the write process will insert a line feed / carriage control character after each write. The module also inserts the '../' in front of all the relative links in the HTML template because when I type and look at the template, I don't want to be distracted by all of the additional dots.

The Python ProcessSetup.cgi module calls StringReplace and ValueReplace which substitute default or real values for all of the fields in the HTML template. ValueReplace adds the 'value=' to the string to be substituted. In the code above, the HTTP template fields are replaced with real vaules (which additional Python code had to retrieve) This converts the template into actual HTML code that can be rendered by a browser.

Finally, the HTML code is printed to the browser to be rendered. This code contains an HTML form statement

<form action="Process.cgi" enctype="application/x-www-form-urlencoded" method="post">

which will start the Process.cgi module when the operator clicks on a submit button or presses the Enter key.

The ProcessSetup.cgi module may perform additional functions, like

Once the operator fills out the screen and clicks on the submit button, the form is sent to the Process.cgi module. The Process.cgi module will

If the form information is consistent (one can never know if it's correct), then the module will produce an HTML page with results. At a minimum, an HTML message of successful completion should be displayed. You should always let the operator know what's going on with your process.

If the form information is inconsistent, then the module will produce one or more error messages, which will be displayed on the form along with all of the information typed by the operator. DON'T MAKE THE OPERATOR RETYPE EVERYTHING ON THE FORM! (Can you tell this is one of my Internet pet peeves?)

The CommonRoutines.py module contains all of the functions that are commonly used by the entire website. For example, the code that adds the '../' to the front of all the relative links is in the CommonRoutines.py module.

The SQLRoutines.py module contains all of the functions that insert, update, delete, and select information from the MySQL database. Because database technology changes, it simplifies maintenance to have all of the SQL routines in one place. This also allows me to use Python constants for the name of the database, the logon and password, so that I can use the same routine in development and deployment.

This first block of Python Constants define the development MySQL databases.


DATABASE_1 = "stories"
DATABASE_2 = "stories"
HOST       = "localhost"
USER       = ""
PASSWORD   = ""

This second block of Python Constants define the deployment MySQL databases. The names and password have been changed to protect my website.


DATABASE_1 = "pythncgpgmng2"
DATABASE_2 = "pythncgpgmng3"
HOST       = "localhost"
USER       = "pythncgpgmng"
PASSWORD   = "*********"

Here's one of the SQL routines, to show how I've used MySQLdb.


def GetStoryCategory(category_id):
    """Get a Story Category row"""
    
    select_sql        = "Select Category_ID"
    select_sql       += "      ,Parent_Category_ID"
    select_sql       += "      ,Category_Name"
    select_sql       += "      ,Category_Description"
    select_sql       += "      ,Category_Creation_Date"
    select_sql       += "      ,Category_Story_Count"
    select_sql       += "      ,Subcategory_Story_Count"
    select_sql       += " from story_category"
    select_sql       += " where Category_ID = " + str(category_id) 

    print select_sql
    
    db                = MySQLdb.connect(db=DATABASE_1, host=HOST, 
                                      user=USER, passwd=PASSWORD)
    c                 = db.cursor()
    c.execute(select_sql)
    values            = c.fetchone()
    c.close()

    return values

The ProcessRoutines.py module contains all of the functions that are commonly used by the ProcessSetup.cgi and Process.cgi modules. You can factor out the common code after you've developed and tested the CGI modules.

It's possible to have more than one Process.cgi modules. A complicated, multi-page form could have several different Process.cgi modules before producing a results page. Intermediate information could be stored on a temporary MySQL database, with a key value passed as a hidden value on the form.

Previous Page: HTML Template, Top Page: Index