|
Instructional Technology Portfolio | Design and Development Tools | Lessons | Zope Lessons Login | Résumé | IT Portfolio | Home |
There are two main ways of processing Zope forms. One is with DTML methods and the other is with Python methods. Since the python way of doing things is not as well documented, I will attempt to show common DTML methods encountered along-side the python equivalent.
This example begins with the very basic case. You have a form, you need to do something with the input and return a resulting page. Some forms, you need to validate the data and re-display the form should the user enter invalid data. A good example of this is the logic behind a login form where you want to ensure the user entered something for both user name and password.
select * from users where email = <dtml-sqlvar email type=string> and password = <dtml-sqlvar password type=string>
<dtml-if "SESSION['isauthorized'] == 0"> <dtml-if start> <dtml-call "REQUEST.set('msg_error', '')"> <dtml-if "not _.has_key('email') or _.len(email) == 0"> <dtml-call "REQUEST.set('msg_error', msg_error + message_error(115))"> </dtml-if> <dtml-if "not _.has_key('password') or _.len(password) == 0"> <dtml-call "REQUEST.set('msg_error', msg_error + message_error(113))"> </dtml-if> <dtml-if "_.len(msg_error) == 0"> <dtml-in "verifyUser(email=_.string.strip(email), password=_.string.strip(password))"> <dtml-call "SESSION.set('userid', userid)"> <dtml-call "SESSION.set('isauthorized', 1)"> <dtml-call "SESSION.set('username', firstname + ' ' + lastname)"> <dtml-call "updateUserSession( lastvisit = lastvisit, userid = userid, n_sessions = n_sessions + 1)"> <dtml-if "SESSION.has_key('back_url')"> <dtml-return "RESPONSE.redirect(SESSION['back_url'])"> <dtml-else> <dtml-return "RESPONSE.redirect(_[root].absolute_url())"> </dtml-if> <dtml-else> <dtml-call "REQUEST.set('msg_error', msg_error + message_error(10))"> </dtml-in> </dtml-if> <dtml-if msg_error><p align="center"><font color=red><dtml-var msg_error></font></p></dtml-if> </dtml-if> <form action="." method="POST"> <input type="hidden" name="start" value="1"> <dtml-unless back_url> <dtml-unless "SESSION.has_key('back_url')"> <dtml-call "SESSION.set('back_url', REQUEST['HTTP_REFERER'])"> </dtml-unless> </dtml-unless> <center> <table border="0" cellpadding="5" cellspacing="0"> <tr> <th colspan=2>If you are a returning shopper, please enter<br> your e-mail address and password to login in. </th> </tr> <tr> <td align="right">E-Mail Address</td> <td align="left"><input name="email" value='<dtml-var email missing="">' size="30"></td> </tr> <tr> <td align="right">Password</td> <td align="left"><input name="password" type="password" size="20"></td> </tr> <tr> <td> </td> <td align="left" align="center"><input type="submit" value="Login" name="login:method"></td> </tr> </table> <p><input type="submit" value="New Shopper Registration" name="new:method"></p> </center> </form> <dtml-else> <dtml-return "RESPONSE.redirect(_[root].absolute_url())"> </dtml-if>
In the above script, we have to set a flag (start) to indicate this is the first time we're calling this form for display in order to skip all the verification code at the beginning. Because we want to be able to prompt the user again (and again) for user name and password, we roll both the verification logic and the form into one DTML document and this technique allows us to avoid a lot of extra DTML codding just to pass input parameters from script to script.
<form action="." method="POST"> <p>Please enter your e-mail address and password to login in.</p> <table> <td align="right">E-Mail Address</td> <td align="left"><input name="email" value="<dtml-var email missing="">" size="30"></td> </tr> <tr> <td align="right">Password</td> <td align="left"><input name="password" type="password" size="20"></td> </tr> <tr> <td> </td> <td align="left" align="center"><input type="submit" value="Login" name="verify:method"></td> </tr> </table> </form>
Note two points of interests about this form:
# checks db for email address and password. If found, updates current session to logged in and # makes note of user's visit in db request = container.REQUEST RESPONSE = request.RESPONSE session = request.SESSION # See if User provided correct credentials to log in msg_error = '' email = request.get('email','') password = request.get('password','') if email == '': msg_error = 'Please provide email in the form of user@somedomain.ext\n' if password == '': msg_error = msg_error + 'Passwords cannot be blank. Please provide password to login.\n' if len(msg_error) == 0: result = container.verifyUser(email=email,password=password) if len(result) == 0: msg_error = 'Could not verify credentials. Please check email address and retype password to try again.' else: session.set('userid',result[0].userid) session.set('isauthorized', 1) session.set('username', result[0].firstname + ' ' + result[0].lastname) container.updateSession( lastvisit = result[0].lastvisit, userid = result[0].userid, n_sessions = result[0].n_sessions + 1) if len(msg_error) <> 0: session.set('msg_error', msg_error) return container.index_html(context, request) else: back_url = session.get('back_url','/') if session.has_key('back_url'): session.delete('back_url') return RESPONSE.redirect(back_url)
Notice how much cleaner and simpler the Python based way of processing forms is! With the logic and the interface cleanly separated, this mechanism is much easier to maintain. Also, your non-technical web-site maintainers will not be so intimidated updating simple forms with the Python approach as they would be with the DTML approach above.
So what is Python's trick for re-supplying values when you have to display the form more than once to get the user's input? Simple, we tell Zope to render the form again, passing the REQUEST object (which has all the information from previous form submission) already populated. Just think, with DTML, you would have had to call <dtml-call REQUEST.set(.... for every input field had you split out the DTML verification logic from the form.
Another aspect to consider, because the Python language is so much cleaner and simpler than DTML, you also have much less code to wade through and debug than otherwise with DTML
| mwlang@cybrains.net | Guest | Login | Home |