Question using CGI in Python

Sam Penrose sam at ddmweb.com
Wed Aug 29 12:27:28 EDT 2001


Your biggest problem is coding style. To make your life a little easier:

1) Make each script a function in a single script. Call them, for
example, printFirstPage(), printSecondPage(), printThirdPage(). (Those
are actually pretty lousy names. The names should reflect what the
fucntions do, and the page-printing logic should be separated from the
db-accessing logic. But you have to start somewhere.)

2) Break out the bulk of the HTML written by each script into
separate files that you read in. For example, "step_one.htm",
"step_two.htm", and "step_three.htm" (again, pick names that describe
what the pages represent or do). In each file, give the submit button a
different value. The button in step_one.htm might read: <input
type="submit" name="action" value="Go to second step"> and in
step_two.htm <input type="submit" name="action" value="Finish">

3) At the bottom of the single script you made in 1), write:
BASIC_HEADER = 'Content-type: text/html\n'
if __name__ == '__main__':
    import cgi
    form = cgi.FieldStorage(keep_blank_values=1)
    try:
        main()
    except:
        print BASIC_HEADER
        print cgi.print_exception()

4) Just above that, write:
def main():
    """Quick and dirty, but should work"""
   page = ''
   if form.has_key('action'):
       action = form['action'].value
        if action == 'Go to second step':
            page = printSecondPage()
        elif action == 'Finish':
            page = printThirdPage()
    if not page: #must be starting out
        page = printFirstPage()
    print BASIC_HEADER
    print page

5) Crude example of what step_two.htm should look like. Note that HTML
needs double-quotes around tag values: 
<html><head><title>Step Two</title></head> 
<body><FORM METHOD="POST'"ACTION="myScript.py">
This is some explanantory text representing what the user sees.
Next line is input the user controls:
<input type="text" name="some_user_preference">
%(hiddenFields)s
<input type="submit" name="action" value="Finish">
</form</body></html>

6) Crude example of what printSecondPage() and helper functions
should look like: 
def printSecondPage():
    if firstPageInputIsValid(): # make sure valid var1 in input
        html = open('step_two.htm').read() # see 5)
        hiddenDict = {'var1':form['var1'].value}
        hiddenFields = makeHiddenFields(hiddenDict)
        return html % {'hiddenFields':hiddenFields}
    else: # reprint first page with error message
       errorMessage = '''The value you entered for var1, "%s",
        was not valid. Please try again.''' % form['var1'].value
       return printFirstPage(errorMessage=errorMessage)

def firstPageInputIsValid():
    if form['var1'].value == 'swordfish': 
        # or looks like a valid email address, or matches the password
        # in the database, or whatever 
        return 1     
    return 0

def makeHiddenFields(hiddenDict):
    """Python 1.5.2 compatible version""""
    hiddenTag = "<input type="hidden" name="%s" value="%s">
    localList = []
    for pair in hiddenDict.items():
        oneField = hiddenTag % pair
        localList.append(oneField)
    import string
    hiddenFields = string.join(localList)
    return hiddenFields

7) More generally:
You should limit non-idented statements to import statements; the
module docstring; definitions of constants, classes, and functions;
and the little blurb in 3) which goes at the bottom of the script.

Do not print raw strings. Assign the strings to variables and print
the variables. Specifically, your HTTP header(s) should be one
variable, your entire HTML page a second, and your traceback a third
(printed only if there is an error). Those three print statements should
suffice for systems thousands of lines long.

If you have a function that is much longer than the ones I've written,
ask your self what it does and write down the answer. Circle every verb
in the answer and move corresponding parts of your original function
into other functions which you call from the first function.

HTH,
s




More information about the Python-list mailing list