[Zope] How to make a ZPT-based form that calls itself? (Part II)

Ken Winter ken at sunward.org
Wed May 18 19:32:29 EDT 2005


In Part I, J Cameron Cooper showed me how to write a ZPT-based form that
displayed a list of database records and gave the user a chance to delete
one of them, after which the form redisplayed itself with a refreshed list
that reflected the deletion just performed.  The core of this was this
Python script, which was called by the form and which called a Z SQL method
to do the deletion:

id = context.REQUEST.get('person_id')
if id:
   container.delete_person(person_id=id)
context.REQUEST.RESPONSE.redirect('deltest.htm')

Now what I need to do is implement a record update form.  This form displays
all the columns of one database record.  The columns values are shown in
text input fields.  The user can write new values into these fields and push
a submit button, which calls this Python script:

id = context.REQUEST.get('person_id')
if id:
   container.update_person(\
      person_id=id,\
      first_name=context.REQUEST.get('first_name'),\
      middle_names=context.REQUEST.get('middle_names'),\
      last_name=context.REQUEST.get('last_name'))
context.REQUEST.RESPONSE.redirect('personform.htm')

This performs the update OK, but instead of redisplaying the page it gives
me:

Site Error
An error was encountered while publishing this resource.
Error Type: AttributeError
Error Value: person_id

The difference between this and the deletion example is that this form
(personform.htm) need to be called with an argument, giving the person_id
that identifies the record it is supposed to display.  I have tried a number
of ways to sneak this argument in, but my limited experience with
Zope/Python syntax has left me unable to guess the right trick.

- Thanks for your help, Ken


> -----Original Message-----
> From: J Cameron Cooper [mailto:zope-l at jcameroncooper.com]
> Sent: Wednesday, May 11, 2005 5:52 PM
> To: ken at sunward.org
> Cc: zope at zope.org
> Subject: Re: [Zope] How to make a ZPT-based form that calls itself?
> 
> Ken Winter wrote:
> >>-----Original Message-----
> >>From: J Cameron Cooper [mailto:zope-l at jcameroncooper.com]
> >>Sent: Wednesday, May 11, 2005 4:27 PM
> >>To: ken at sunward.org
> >>Cc: zope at zope.org
> >>Subject: Re: [Zope] How to make a ZPT-based form that calls itself?
> >>
> >>Ken Winter wrote:
> >>
> >>>Hi Zopers -
> >>>
> >>>I'm trying to make a ZPT-based HTML form that:
> >>>
> >>>1. Displays the records in a MySQL 'Person' table;
> >>>2. Offers a field for updating this table (in my simple test example,
> it
> >>>accepts the Id of a Person to delete);
> >>>3. When you push its 'Submit' button, updates the database; and then
> >>>4. Automatically redisplays itself, showing the updated 'Person'
> >>
> >>records.
> >>
> >>>After a lot of help from the folks on various Zope lists, I've made it
> >>>through steps 1-3, but I'm stuck on step 4 and I can't find an example
> >>
> >>or
> >>
> >>>tutorial telling me how to do it.
> >>>
> >>>The relevant code snippets are:
> >>>
> >>>The ZPT's body...
> >>>
> ...
> >>>
> >>>...The one-line Python script "delete_person_py" that the form's action
> >>>attribute calls...
> >>>
> >>>container.delete_person(person_id=context.REQUEST.get('person_id'))
> >>>
> >>>...The Z SQL method delete_person(person_id) that the Python script
> >>
> >>calls...
> >>
> >>>delete from person where <dtml-sqltest person_id op=eq type=int>
> >>>
> >>>...And a URL to the test page in its current incarnation...
> >>>
> >>>http://dhat.vega.zettai.net/clients/ridhwan/dhr3/deltest.htm
> >>>
> >>>What's wrong with this page is that you have to hit the "Refresh This
> >>
> >>Page"
> >>
> >>>link to get it to do what I want it to do automatically.
> >>>
> >>>I suspect that what I'm missing is some basic HTML knowledge.  But
> >>
> >>whatever
> >>
> >>>it is, I'd appreciate your help in suggesting the missing piece.
> >>
> >>You submit to a script, going that url, and the script is responsible
> >>for providing the output of the page.
> >>
> >>Since you write no output, you see no action in your browser. Some
> >>browsers may display a blank page, which probably would have been more
> >>helpful to you.
> >>
> >>You want your script to do something. It might print out some text to
> >>form HTML, but that's nasty. It usually will either (a) call some other
> >>object, like a page template, to provide output, or (b) do a redirect.
> >>
> >>Case A:
> >>   return context.some_page()
> >>
> >>Case B:
> >>   context.REQUEST.RESPONSE.redirect('some_page')
> >>
> >
> > GREAT!!  Case B works perfectly (and it would have taken me forever to
> guess
> > this solution).  Case A didn't work when written as
> >
> > return context.deltest.htm()
> >
> > but, who cares?
> 
> Look at your Python. It understands a dot as an attribute access. That's
> why Zope historically avoids dotted object names. Witness 'index_html'.
> 
> You may use dictionary lookup:
> 
>   context['deltest.htm']()
> 
> or getattr.
> 
> >>In your case, since this is a destructive method, you probably want do a
> >>redirect, back to your listing.
> >
> > "Destructive" means that the script has a side-effect (deleting the
> Person),
> > right?
> 
> Correct.
> 
> > Why in that case is a redirect better?
> 
> Because you don't end up on the script (no bad bookmark), and reload of
> that page won't carry the previous POST payload. See the very recent
> post about redirect-after-post.
> 
> >>A more advanced and flexible technique is to use FormController. With
> >>that, you specify by configuration if you want redirect or traverse and
> >>where to go based on the results of the script (success, failure, some
> >>other state.)
> >
> > I'm looking into this - looks promising at first glance.  I note that
> the
> > Add dialog warns that "these are normally useful only inside a CMF
> site."
> > Mine is not (at least currently) a CMF site.  Should I worry about that?
> 
> A Plone site it a superset of a CMF site. But it you're outside a CMF
> framework entirely, formcontroller may not work, as it needs to install
> a tool. Dunno if it'll install standalone.
> 
> 		--jcc
> 
> --
> "Building Websites with Plone"
> http://plonebook.packtpub.com/




More information about the Zope mailing list