Solved

python cgi handling of html textarea inputs with template substitution

Posted on 2011-03-16
7
1,385 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
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
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

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Variable is a place holder or reserved memory locations to store any value. Which means whenever we create a variable, indirectly we are reserving some space in the memory. The interpreter assigns or allocates some space in the memory based on the d…
Active Directory replication delay is the cause to many problems.  Here is a super easy script to force Active Directory replication to all sites with by using an elevated PowerShell command prompt, and a tool to verify your changes.
Learn the basics of strings in Python: declaration, operations, indices, and slicing. Strings are declared with quotations; for example: s = "string": Strings are immutable.: Strings may be concatenated or multiplied using the addition and multiplic…
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.

770 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