Web Form Error Handling Techniques

Samuel Walters swalters_usenet at yahoo.com
Sun Jan 18 04:22:33 EST 2004


| Sean Abrahams said |

> def insertData(data):
> 
>      # test data for validity
>      if not data['name'].isalpha():
>         raise InvalidDataError(data['name'], "Name contains non-alpha
>         characters")
>      if not data['age'].isdigit():
>         raise InvalidDataError(data['age'], "Age contains non-digit
>         characters")
> 
>      sql = """
>      INSERT INTO people (name, age) VALUES ('%s', '%s')
>      """ % (data['name'], data['age'])
> 
>      executeSQL(sql)
> 
> I should first check to see if the data is valid, meaning that the
> name contains only alpha characters and the age only containing
> numeric characters.
> 
> If I raise an exception, how would one handle the reprinting of the
> web form with a red * next to the field that contains invalid data? If
> one field is in error, I can see that upon receiving an exception you
> can have your code just reprint the web form with the red star, but
> what about when both fields are in error, do you have the exception
> create a list which then your code checks to see if it exists and then
> loops through it to know what fields are in error?

So, what you're saying is that you wish to have the exception pass
information on which, of each piece, of the data is invalid?

Test it all, and then raise an error based on *all* the data that is
invalid.

For instance:

------
class InvalidDataError(Exception):
    """InvalidDataError
       Attributes: values - a list of tuples of the form:
          (name, data, offense)
          Where name is the name of the field causing problems
          Data is the data the field contained.
          Offense is a string describing the problem encountered.
    """
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(value)
        

def insertData(data):

     errors = []
     if not data['name'].isalpha():
         errors.append(('name', data['name'], "Name contains non-alpha characters"))
     if not data['age'].isdigit():
         errors.append(('age', data['age'], "Age contains non-digit characters"))

     if len(errors):
         raise InvalidDataError(errors)
                    
     sql = """
     INSERT INTO people (name, age) VALUES ('%s', '%s')
     """ % (data['name'], data['age'])

     executeSQL(sql)


good={"name":"bob", "age":"12343"}
bad={"name":"bob#", "age":"14"}
worse={"name":"bob", "age":"ni!"}
ugly={"name":"v@$$#", "age":"ni!"}

def test(data):
    try:
        insertData(data)
    except InvalidDataError, e:
        print "Data: %s failed with errors:"%(str(data))
        for x in e.value:
            name, data, problem = x
            print "Field \"%s\" had bad data \"%s\" and reported \"%s\" as the problem."%(name, data, problem)
        print
    else:
        print "Good %s found to be A-Ok!"%(str(data))
        print

test(good)
test(bad)
test(worse)
test(ugly)
------

Now, with that code, you can format your user response any way you want.

User defined exceptions can toss around any type of data.
See section 8.5 of the tutorial for examples:
http://www.python.org/doc/current/tut/node10.html

Also, one other test that needs to be performed is to check whether the
data dictionary passed to insertData contains each of the fields required.
One checks this with data.has_key('name').  If you get passed a bad piece
of data, then you can handle it gracefully.  Personally, I would create a
different exception for that because the cause could be either programmer
error, or bad data being passed to the program.

Personally, though, I wouldn't wait until just before inserting the data
to check it's validity.  I prefer to catch invalid data as *early* as
possible.  When I'm writing CGI and other web scripts, the outline of my
program looks like this:

Check for the existence and validity of each piece of data.
If error exists:
    Generate and return an error page to the user.
Else:
    Handle the data and generate a response page for the user.

It's a good habit to check the validity of each piece of data as soon as
it's received.  This lets you separate problems where the user sent you
bad data, and problems where you messed up the data along the way.  If the
user passed you decent data, then the only error they should see is some
form of "Internal Server Error."		

HTH

Sam Walters.

-- 
Never forget the halloween documents.
http://www.opensource.org/halloween/
""" Where will Microsoft try to drag you today?
    Do you really want to go there?"""




More information about the Python-list mailing list