Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1511
  • Last Modified:

python cgi handling of html textarea inputs with template substitution

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
sara_bellum
Asked:
sara_bellum
  • 4
  • 3
1 Solution
 
clockwatcherCommented:
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
 
sara_bellumAuthor Commented:
Thanks very much!! That should wrap it up, but I'd like to check a few things before closing this, hopefully tomorrow :)
0
 
sara_bellumAuthor Commented:
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
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
clockwatcherCommented:
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
 
clockwatcherCommented:
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
 
sara_bellumAuthor Commented:
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
 
sara_bellumAuthor Commented:
Very very helpful !!
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now