Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

python cgi handling of html textarea inputs with template substitution

Posted on 2011-03-16
7
Medium Priority
?
1,480 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Basic Security of Your VPC

So, you’ve got this shiny new VPC and a fancy new application configured on your EC2 servers ready to go. This application is only accessible from your computer, which is great for security, but you need your users to be able to access it! So, what’s the easiest way to do this?

 
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 2000 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

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.

Question has a verified solution.

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

Introduction On September 29, 2012, the Python 3.3.0 was released; nothing extremely unexpected,  yet another, better version of Python. But, if you work in Microsoft Windows, you should notice that the Python Launcher for Windows was introduced wi…
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…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…

670 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