Solved

python cgi handling of html textarea inputs with template substitution

Posted on 2011-03-16
7
1,359 Views
Last Modified: 2013-12-25
I've written a simple cgi script to process two form elements, a text input and a textarea input, and print user inputs to the form after the user presses the submit button. It works for the text input but not for the textarea. Why? The script and the html page are attached. I'm using python template substitution.
import cgi
import re
import cgitb; cgitb.enable()
from string import Template

form = cgi.FieldStorage()
fields = {}
template_form = 'text_box.html'
name_message = 'Your name: '
comments_message = 'Type in your comments here:'
form_fields = [ 'your_name', 'comments' ]

def print_form(name_message=None, comments_message=None, **kw):

    fields = kw.get('fields', {})

    for field_name in form_fields:
        if isinstance(form.getvalue(field_name), list):
            fields[field_name] = form.getfirst(field_name)
        else:
            fields[field_name] = form.getvalue(field_name)

    for key in fields.keys():
        if fields[key] == None:
            fields[key] = ' '

    if fields['your_name'] != ' ' and fields['comments'] != ' ':
        if len(fields['comments']) > 1000:
            name_message = 'Your name is: '
            comments_message = 'Your comments are too long'
        else:
            name_message = 'Your name is: '
            comments_message = 'We have read your comments and they are:'
            print 'Your name: ', fields['your_name'], '<br/>Your comments:', fields['comments'], '<br/>'
            print '<hr width="50%" align="left">'

    else:
        name_message = 'Your name: '
        comments_message = 'Type in your comments here:'

    try:
        s = Template(open(template_form).read())
        print s.substitute(name_message=name_message, comments_message=comments_message, **fields)

    except IOError:
        print 'Could not read form!'
        sys.exit(1)

print "Content-Type: text/html\n\n"

print_form(name_message=None, comments_message=None, fields=fields)

Open in new window

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Python Form</title>
</head>
<body>
<form method="post" action="text_area.cgi">
    <p>${name_message}<input type="text" name="your_name" maxlength="100" value="${your_name}"></p>
    <p>${comments_message}</p>
    <textarea name="comments" cols="50" rows="10" maxlength="800" value="${comments}"></textarea><br/>
    <input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Open in new window

0
Comment
Question by:sara_bellum
  • 4
  • 3
7 Comments
 
LVL 25

Expert Comment

by:clockwatcher
ID: 35153512
Textarea's don't get there initial value based on the value attribute.  They get it based on their content.  Try changing this:

<textarea name="comments" cols="50" rows="10" maxlength="800" value="${comments}"></textarea>

To this:

<textarea name="comments" cols="50" rows="10" maxlength="800">${comments}</textarea>
0
 

Author Comment

by:sara_bellum
ID: 35153912
Thanks very much!! That should wrap it up, but I'd like to check a few things before closing this, hopefully tomorrow :)
0
 

Author Comment

by:sara_bellum
ID: 35161935
I was hoping that the problem would be easy to solve but it's not, because forms have more than text boxes and text areas - they also have radio buttons and check boxes, and I don't know how to make them maintain a persistent state with python template substitution. I took a stab at it which I attach - the print statements work, so I'm missing something.

I researched the problem and there's a website that addresses the problem of check boxes and radio buttons at http://www.voidspace.org.uk/python/articles/cgi_web_applications_two.shtml  But this script doesn't address the question of maintaining user inputs in text areas, so I'm still stuck.

I'd rather stick with python template substitution if there's a way to address the problem in that way. Let me know if I need to open a new question.
 
form = cgi.FieldStorage()
fields = {}
template_form = 'text_box.html'
error_message = ' '
form_fields = [ '_charset_', 'your_name', 'red', 'blue', 'green', 'yellow', 'food', 'comments', \
                         'check1', 'check2', 'check3', 'check4', 'check5', 'check6', 'check7', 'submit' ]
check_colors = [ 'red', 'blue', 'green', 'yellow' ]
check_radio = [ 'check5', 'check6', 'check7' ]
check_box = [ 'check1', 'check2', 'check3', 'check4' ]
form_dict = { 'Name': ' ', 'red': ' ', 'blue': ' ', 'green': ' ', 'yellow': ' ', 'Food': ' ', 'Comments': ' ' }
required = ['Name', 'red', 'blue', 'green', 'yellow', 'Food', 'Comments']
errors = []
colors = []

def print_form(error_message=None, **kw):

    fields = kw.get('fields', {})

    for field_name in form_fields:
        if isinstance(form.getvalue(field_name), list):
            fields[field_name] = form.getfirst(field_name)
        else:
            fields[field_name] = form.getvalue(field_name)

    for key in fields.keys():
        #print key
        if fields[key] == None:
            fields[key] = ' '

        for item in check_colors:
            if item == key:
                if form.getvalue(key):
                    fields[key] = 'on'
                    colors.append(key)
                else:
                    fields[key] = 'off'

        for field in form_dict.keys():
            if field == key:
                if fields[key] == 'on':
                    form_dict[field] = 'on'
                else:
                    form_dict[field] = 'off'

        if key == 'red':
            if fields[key] == 'on':
                check1 = 'checked'
                print 'red is on,', check1, 'should be checked <br/>'
            else:
                check1 = ''

        if key == 'blue':
            if fields[key] == 'on':
                check2 = 'checked'
                print 'blue is on,', check2, 'should be checked <br/>'
            else:
                check2 = ''

        if key == 'green':
            if fields[key] == 'on':
                check3 = 'checked'
                print 'green is on,', check3, 'should be checked <br/>'
            else:
                check3 = ''

        if key == 'yellow':
            if fields[key] == 'on':
                check4 = 'checked'
                print 'yellow is on,', check4, 'should be checked <br/>'
            else:
                check4 = ''

        if fields[key] == 'chicken':
            check5 = 'checked'
            print 'chicken was selected, radio button should be checked <br/>'
        else:
            check5 = ''

        if fields[key] == 'beef':
            check6 = 'checked'
            print 'beef was selected, radio button should be checked <br/>'
        else:
            check6 = ''

        if fields[key] == 'fish':
            check7 = 'checked'
            print 'fish was selected, radio button should be checked <br/>'
        else:
            check6 = ''

    form_dict['Food'] = form.getvalue('food')

    if fields['your_name']:
        form_dict['Name'] = fields['your_name']

    if fields['comments']:
        if len(fields['comments']) > 1000:
                errors.append('Your comments are too long!')
        else:
            form_dict['Comments'] = fields['comments']

    if form_dict['Food'] == ' ':
        errors.append('Missing food!')
    elif form_dict['Name'] == ' ':
        errors.append('Missing name!')
    elif form_dict['Comments'] == ' ':
        errors.append('Missing comments!')

    if len(colors) == 0:
        errors.append('Missing color!')

    if form.getvalue('submit'):
        error_message = ' '
        print '<br/>'
        for item in required:
            for field in form_dict.keys():
                if item == field and form_dict[field] != 'off':
                    print field, ':', form_dict[field], '<br/>'
        print '<hr width="50%" align="left">'

        if len(errors) > 0:
            print errors
            error_message = 'Complete all four fields!'
    else:
        error_message = ' '

    try:
        s = Template(open(template_form).read())
        print s.substitute(error_message=error_message, **fields)

    except IOError:
        print 'Could not read form!'
        sys.exit(1)

print "Content-Type: text/html\n\n"

print_form(error_message=None, fields=fields)

Open in new window

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Python Form</title>
</head>
<body>
<form method="post" action="text_area.cgi">
    <div>${error_message}</div>
    <p>Your name: <input type="text" name="your_name" maxlength="100" value="${your_name}"></p>
    <p> Your colors: <br/>
    <input type="checkbox" name="red" value=" " ${check1} />  Red
    <input type="checkbox" name="blue" value=" " ${check2} /> Blue <br />
    <input type="checkbox" name="green" value=" " ${check3} /> Green
    <input type="checkbox" name="yellow" value=" " ${check4} /> Yellow </p>
    <p> Your menu choice:
    <input type="radio" name="food" value="chicken" ${check5} /> Chicken
    <input type="radio" name="food" value="beef" ${check6} /> Beef
    <input type="radio" name="food" value="fish" ${check7} /> Fish </p>
    <p>Your comments</p>
    <textarea name="comments" cols="50" rows="10" maxlength="800">${comments}</textarea><br/>
    <input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Open in new window

0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 25

Expert Comment

by:clockwatcher
ID: 35170178
The reason that what you're doing isn't working is because you're setting a variable named check1 but you're not passing that variable into your template.  You're passing error_message and **fields:

   s.substitute(error_message=error_message, **fields)

Open in new window


Setting fields['check1'] would work:

        if key == 'red':
            if fields[key] == 'on':
                fields['check1'] = 'checked'
                print 'red is on,', fields['check1'], 'should be checked <br/>'
            else:
                fields['check1'] = ''

Open in new window

0
 
LVL 25

Accepted Solution

by:
clockwatcher earned 500 total points
ID: 35170240
I cleaned up your checkbox and radiobutton code a little bit and modified the template to work with the new code.  It may help give you some ideas of how to go about handling checkboxes and radio buttons.

#!/usr/bin/python
import sys
import cgi
import re
import cgitb; cgitb.enable()
from string import Template

form = cgi.FieldStorage()
fields = {}
template_form = 'text_box.html'
error_message = ' '
form_fields = [ '_charset_', 'your_name', 'red', 'blue', 'green', 'yellow', 'food', 'comments', \
                         'check1', 'check2', 'check3', 'check4', 'check5', 'check6', 'check7', 'submit' ]
check_colors = [ 'red', 'blue', 'green', 'yellow' ]
check_radio = [ 'check5', 'check6', 'check7' ]
check_box = [ 'check1', 'check2', 'check3', 'check4' ]
form_dict = { 'Name': ' ', 'red': ' ', 'blue': ' ', 'green': ' ', 'yellow': ' ', 'Food': ' ', 'Comments': ' ' }
required = ['Name', 'red', 'blue', 'green', 'yellow', 'Food', 'Comments']
errors = []
colors = []

def print_form(error_message=None, **kw):

    fields = kw.get('fields', {})

    for field_name in form_fields:
        if isinstance(form.getvalue(field_name), list):
            fields[field_name] = form.getfirst(field_name)
        else:
            fields[field_name] = form.getvalue(field_name)

    for color in ('red', 'blue', 'green', 'yellow'):
        if color in form:
            fields['color_' + color] = 'checked'
            print "%s is checked <br/>" % (color)
            colors.append(color)
        else:
            fields['color_' + color] = ''
    
    for meal in ('beef', 'chicken', 'fish'):
        fields['food_' + meal] = ''

    selected_food = form.getfirst('food','')  
    if selected_food != '':
        fields['food_' + selected_food] = 'checked'
        form_dict['Food'] = selected_food

    if fields['your_name']:
        form_dict['Name'] = fields['your_name']

    if fields['comments']:
        if len(fields['comments']) > 1000:
                errors.append('Your comments are too long!')
        else:
            form_dict['Comments'] = fields['comments']

    if form_dict['Food'] == ' ':
        errors.append('Missing food!')
    elif form_dict['Name'] == ' ':
        errors.append('Missing name!')
    elif form_dict['Comments'] == ' ':
        errors.append('Missing comments!')

    if len(colors) == 0:
        errors.append('Missing color!')

    if form.getvalue('submit'):
        error_message = ' '
        print '<br/>'
        for item in required:
            for field in form_dict.keys():
                if item == field and form_dict[field] != 'off':
                    print field, ':', form_dict[field], '<br/>'
        print '<hr width="50%" align="left">'

        if len(errors) > 0:
            print errors
            error_message = 'Complete all four fields!'
    else:
        error_message = ' '

    try:
        s = Template(open(template_form).read())
        print s.substitute(error_message=error_message, **fields)

    except IOError:
        print 'Could not read form!'
        sys.exit(1)

print "Content-Type: text/html\n\n"

print_form(error_message=None, fields=fields)

Open in new window


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Python Form</title>
</head>
<body>
<form method="post" >
    <div>${error_message}</div>
    <p>Your name: <input type="text" name="your_name" maxlength="100" value="${your_name}"></p>
    <p> Your colors: <br/>
    <input type="checkbox" name="red" value=" " ${color_red} />  Red
    <input type="checkbox" name="blue" value=" " ${color_blue} /> Blue <br />
    <input type="checkbox" name="green" value=" " ${color_green} /> Green
    <input type="checkbox" name="yellow" value=" " ${color_yellow} /> Yellow </p>
    <p> Your menu choice:
    <input type="radio" name="food" value="chicken" ${food_chicken} /> Chicken
    <input type="radio" name="food" value="beef" ${food_beef} /> Beef
    <input type="radio" name="food" value="fish" ${food_fish} /> Fish </p>
    <p>Your comments</p>
    <textarea name="comments" cols="50" rows="10" maxlength="800">${comments}</textarea><br/>
    <input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Open in new window

0
 

Author Comment

by:sara_bellum
ID: 35170794
I made some minor edits that I post here for the record (I don't think the radio button values persisted without the else statement) but your feedback clockwatcher is fabulous. Thanks very much!!

It's wonderful to be able to write a script the way I wish to write it rather than depend on the way someone else did simply because their way works (and is posted on the Internet) and mine does not, for reasons which I can't understand. Now I know why there was a problem and I know the fix and life is good.

EE ROCKS
#!/usr/bin/python

import sys
import cgi
import re
import cgitb; cgitb.enable()
from string import Template

form = cgi.FieldStorage()
fields = {}
template_form = 'page_ee.html'
error_message = ' '
form_fields = [ '_charset_', 'your_name', 'red', 'blue', 'green', 'yellow', 'food', 'comments', \
                         'check1', 'check2', 'check3', 'check4', 'check5', 'check6', 'check7', 'submit' ]
check_colors = [ 'red', 'blue', 'green', 'yellow' ]
check_radio = [ 'check5', 'check6', 'check7' ]
check_box = [ 'check1', 'check2', 'check3', 'check4' ]
form_dict = { 'Name': ' ', 'red': ' ', 'blue': ' ', 'green': ' ', 'yellow': ' ', 'Food': ' ', 'Comments': ' ' }
required = ['Name', 'red', 'blue', 'green', 'yellow', 'Food', 'Comments']
errors = []
colors = []

def print_form(error_message=None, **kw):

    fields = kw.get('fields', {})

    for field_name in form_fields:
        if isinstance(form.getvalue(field_name), list):
            fields[field_name] = form.getfirst(field_name)
        else:
            fields[field_name] = form.getvalue(field_name)
            
        if form.getvalue(field_name) == None:
            fields[field_name] = ''

    for color in ('red', 'blue', 'green', 'yellow'):
         
        if color in form:
            fields['color_' + color] = 'checked'
            print "%s is the color that is checked <br/>" % (color)
            colors.append(color)
        else:
            fields['color_' + color] = ''
        
    for meal in ('beef', 'chicken', 'fish'):
        fields['food_' + meal] = ''

    selected_food = fields['food']
    if selected_food != '':
        fields['food_' + selected_food] = 'checked'
        print selected_food, "is the food that is checked <br/>" 
    else:
        fields['food_' + selected_food] = ''
   
    if fields['your_name']:
        form_dict['Name'] = fields['your_name']

    if fields['comments']:
        if len(fields['comments']) > 1000:
                errors.append('Your comments are too long!')
        else:
            form_dict['Comments'] = fields['comments']

    if form_dict['Food'] == ' ':
        errors.append('Missing food!')
    elif form_dict['Name'] == ' ':
        errors.append('Missing name!')
    elif form_dict['Comments'] == ' ':
        errors.append('Missing comments!')

    if len(colors) == 0:
        errors.append('Missing color!')

    if form.getvalue('submit'):
        if len(errors) > 0:
            print errors
            error_message = 'Complete all four fields!'
        else:
            error_message = ' '
    else:
        error_message = ' '

    try:
        s = Template(open(template_form).read())
        print s.substitute(error_message=error_message, **fields)

    except IOError:
        print 'Could not read form!'
        sys.exit(1)

print "Content-Type: text/html\n\n"

print_form(error_message=None, fields=fields)

Open in new window

0
 

Author Closing Comment

by:sara_bellum
ID: 35170862
Very very helpful !!
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Less strange, but still introduction This introduction was added (1st August, 2011) to reflect some reactions.  Firstly, the term basics in the title of the article...  As any other word, it is a symbol with meaning attached to the word by some a…
Installing Python 2.7.3 version on Windows operating system For installing Python first we need to download Python's latest version from URL" www.python.org " You can also get information on Python scripting language from the above mentioned we…
Learn the basics of while and for loops in Python.  while loops are used for testing while, or until, a condition is met: The structure of a while loop is as follows:     while <condition>:         do something         repeate: The break statement m…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now