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

2005-05-19 Thread Lennart Regebro
On 5/19/05, Ken Winter [EMAIL PROTECTED] wrote:
 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.

Well, the generic method is to create a script that you call in the
start of you ZPT that returns a dictionary with all the data to be
displayed.  This can also be the same script that actually does the
deletion.

http://blogs.nuxeo.com/sections/blogs/lennart_regebro/2005_04_19_python_statement/

May explain it a bit more, and if not, I should write something clearer. :^)
-- 
Lennart Regebro, Nuxeo http://www.nuxeo.com/
CPS Content Management http://www.cps-project.org/
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


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

2005-05-19 Thread Ken Winter
 -Original Message-
 From: Lennart Regebro [mailto:[EMAIL PROTECTED]
 Sent: Thursday, May 19, 2005 4:36 AM
 To: [EMAIL PROTECTED]
 Cc: J Cameron Cooper; zope@zope.org
 Subject: Re: [Zope] How to make a ZPT-based form that calls itself? (Part
 II)
 
 On 5/19/05, Ken Winter [EMAIL PROTECTED] wrote:
  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.
 
 Well, the generic method is to create a script that you call in the
 start of you ZPT that returns a dictionary with all the data to be
 displayed.  This can also be the same script that actually does the
 deletion.
 
 http://blogs.nuxeo.com/sections/blogs/lennart_regebro/2005_04_19_python_st
 atement/
 
 May explain it a bit more, and if not, I should write something clearer.

Nor clearer - your blog is quite clear - but more elementary, for us
novices.  I'm very attracted to your idea of one Python call that takes care
of returning all the data that the page needs.  But I'm not sure just what
you are including in the term data:

* I assume you include data retrieved from (and updated in) an underlying
relational database.

* Does data also include parameters (or arguments, or query string
variables, or whatever you call them) passed from one HTML page to the next?
This parameter-passing is what I seem to be having trouble with.  How does
that script get the info it needs from the previous page?  In my example,
when my personform.htm updates a record and then re-calls itself, how does
it get the person_id identifying the record it's supposed to display the
second time around?

I have a feeling that there's some point I'm just not getting here, but that
I'm too new to this to figure out what it is.

- Ken


___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


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

2005-05-19 Thread Lennart Regebro
On 5/19/05, Ken Winter [EMAIL PROTECTED] wrote:
 * I assume you include data retrieved from (and updated in) an underlying
 relational database.
 
 * Does data also include parameters (or arguments, or query string
 variables, or whatever you call them) passed from one HTML page to the next?

Sure.

 This parameter-passing is what I seem to be having trouble with.  How does
 that script get the info it needs from the previous page?  In my example,
 when my personform.htm updates a record and then re-calls itself, how does
 it get the person_id identifying the record it's supposed to display the
 second time around?

You put it in a hidden input-field.

 I have a feeling that there's some point I'm just not getting here, but that
 I'm too new to this to figure out what it is.

-- 
Lennart Regebro, Nuxeo http://www.nuxeo.com/
CPS Content Management http://www.cps-project.org/
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


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

2005-05-19 Thread Ken Winter
 -Original Message-
 From: Lennart Regebro [mailto:[EMAIL PROTECTED]
 Sent: Thursday, May 19, 2005 11:07 AM
 To: [EMAIL PROTECTED]
 Cc: J Cameron Cooper; zope@zope.org
 Subject: Re: [Zope] How to make a ZPT-based form that calls itself? (Part
 II)
 
 On 5/19/05, Ken Winter [EMAIL PROTECTED] wrote:
  * I assume you include data retrieved from (and updated in) an
 underlying
  relational database.
 
  * Does data also include parameters (or arguments, or query string
  variables, or whatever you call them) passed from one HTML page to the
 next?
 
 Sure.
 
  This parameter-passing is what I seem to be having trouble with.  How
 does
  that script get the info it needs from the previous page?  In my
 example,
  when my personform.htm updates a record and then re-calls itself, how
 does
  it get the person_id identifying the record it's supposed to display the
  second time around?
 
 You put it in a hidden input-field.
 
That's what I've been doing (I think), and it's not working.  Let me paste
in a listing of the whole div tag that I'm using (with some irrelevant
bits clipped out):

div tal:repeat=person
python:here.dbobs.read_person_by_id_py(context.REQUEST.person_id)
table height=fit width=fit border=0 align=left cellpadding=0
cellspacing=0
  tr height=fit 
...
td width=fit align=left emstrong 
font size=+2p align=left tal:content=string:
${person/first_name} ${person/middle_names} ${person/last_name}Name
Filler/p/font
/strong/em/td
  /tr
/tablebr
pnbsp;/pbr
form name=form1 id=form1 method=post
action=dbobs/update_person_py
  table width=fit border=0 cellspacing=0 cellpadding=0
  tr height=fit
td width=fit align=rightemnbsp;nbsp;First
Name:nbsp;/em/td
td width=fitinput type=text name=first_name value=
tal:attributes=value string:${person/first_name}//td
  /tr
  tr height=fit
td width=fit align=rightemnbsp;nbsp;Middle
Name(s):nbsp;/em/td
td width=fitinput type=text name=middle_names value=
tal:attributes=value string:${person/middle_names}//td
  /tr
  tr height=fit
td width=fit align=rightemnbsp;nbsp;Last Name:nbsp;/em/td
td width=fitinput type=text name=last_name value=
tal:attributes=value string:${person/last_name}//td
  /tr
/table
input type=hidden name=person_id value= tal:attributes=value
string:${person/person_id}/
  p 
input type=submit name=Submit value=Save Changes /
input type=reset name=Reset value=Cancel Changes /
  /p
/form
/div

The tal:repeat in the first line is my attempt to grab all my data at the
start.  The hidden input field at the bottom is my attempt to pass the
person_id along when the page is trying to re-call itself.  The whole thing
works OK when the page is called from elsewhere, passing the person_id in
the form of a URL argument string along these lines:
personform.htm?person_id=35.  But it doesn't work when the Python script 
update_person_py() called by personform.htm itself tries to re-call
personform.htm, trusting the hidden field to convey the person_id data.
Instead, the data update is performed but the next thing the browser shows
is an AttributeError=person_id.  The body of the update_person_py script
is:

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')

What's wrong with this picture?

- Thanks again, Ken


___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


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

2005-05-19 Thread Lennart Regebro
What's wrong with this picture?

This:
   context.REQUEST.RESPONSE.redirect('personform.htm')

When you do this, you loose everything in the form. When you then in
the personform.htm do context.REQUEST.person_id you get a key-error.
-- 
Lennart Regebro, Nuxeo http://www.nuxeo.com/
CPS Content Management http://www.cps-project.org/
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


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

2005-05-19 Thread Ken Winter
 -Original Message-
 From: Lennart Regebro [mailto:[EMAIL PROTECTED]
 Sent: Thursday, May 19, 2005 12:03 PM
 To: [EMAIL PROTECTED]
 Cc: J Cameron Cooper; zope@zope.org
 Subject: Re: [Zope] How to make a ZPT-based form that calls itself? (Part
 II)
 
 What's wrong with this picture?
 
 This:
context.REQUEST.RESPONSE.redirect('personform.htm')
 
 When you do this, you loose everything in the form. When you then in
 the personform.htm do context.REQUEST.person_id you get a key-error.

Assuming the data loss is due to the 'redirect', I tried substituting this
alternative line, suggested by JCC earlier, into the script:

context['personform.htm']()

But that just changed the error to KeyError: 'personform_htm'.


___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists - 
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


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

2005-05-19 Thread Lennart Regebro
On 5/19/05, Ken Winter [EMAIL PROTECTED] wrote:
 But that just changed the error to KeyError: 'personform_htm'.

Well, it's 'personform.htm', not undescore, right?

-- 
Lennart Regebro, Nuxeo http://www.nuxeo.com/
CPS Content Management http://www.cps-project.org/
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


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

2005-05-19 Thread Tino Wildenhain
Am Donnerstag, den 19.05.2005, 11:56 -0400 schrieb Ken Winter:
  -Original Message-
  From: Lennart Regebro [mailto:[EMAIL PROTECTED]
  Sent: Thursday, May 19, 2005 11:07 AM
  To: [EMAIL PROTECTED]
  Cc: J Cameron Cooper; zope@zope.org
  Subject: Re: [Zope] How to make a ZPT-based form that calls itself? (Part
  II)
  
  On 5/19/05, Ken Winter [EMAIL PROTECTED] wrote:
   * I assume you include data retrieved from (and updated in) an
  underlying
   relational database.
  
   * Does data also include parameters (or arguments, or query string
   variables, or whatever you call them) passed from one HTML page to the
  next?
  
  Sure.
  
   This parameter-passing is what I seem to be having trouble with.  How
  does
   that script get the info it needs from the previous page?  In my
  example,
   when my personform.htm updates a record and then re-calls itself, how
  does
   it get the person_id identifying the record it's supposed to display the
   second time around?
  
  You put it in a hidden input-field.
  
 That's what I've been doing (I think), and it's not working.  Let me paste
 in a listing of the whole div tag that I'm using (with some irrelevant
 bits clipped out):
 
 div tal:repeat=person
 python:here.dbobs.read_person_by_id_py(context.REQUEST.person_id)

the read_person_by_id_py can probably read the request variable
by its own. So no need to pass it like that.

 table height=fit width=fit border=0 align=left cellpadding=0
 cellspacing=0
   tr height=fit 
 ...
   td width=fit align=left emstrong 
 font size=+2p align=left tal:content=string:

Ugh! Make yourself familar with moden HTML and CSS, this saves a lot
of typing - and makes smaller templates.

 ${person/first_name} ${person/middle_names} ${person/last_name}Name
 Filler/p/font
 /strong/em/td
   /tr
 /tablebr
 pnbsp;/pbr
 form name=form1 id=form1 method=post
 action=dbobs/update_person_py
   table width=fit border=0 cellspacing=0 cellpadding=0
   tr height=fit
 td width=fit align=rightemnbsp;nbsp;First
 Name:nbsp;/em/td
 td width=fitinput type=text name=first_name value=
 tal:attributes=value string:${person/first_name}//td

value person/first_name would be ok.

   /tr
   tr height=fit
 td width=fit align=rightemnbsp;nbsp;Middle
 Name(s):nbsp;/em/td
 td width=fitinput type=text name=middle_names value=
 tal:attributes=value string:${person/middle_names}//td
   /tr
   tr height=fit
 td width=fit align=rightemnbsp;nbsp;Last Name:nbsp;/em/td
 td width=fitinput type=text name=last_name value=
 tal:attributes=value string:${person/last_name}//td
   /tr
 /table
 input type=hidden name=person_id value= tal:attributes=value
 string:${person/person_id}/
   p 
 input type=submit name=Submit value=Save Changes /
 input type=reset name=Reset value=Cancel Changes /
   /p
 /form
 /div
 
 The tal:repeat in the first line is my attempt to grab all my data at the
 start.  The hidden input field at the bottom is my attempt to pass the
 person_id along when the page is trying to re-call itself.  The whole thing
 works OK when the page is called from elsewhere, passing the person_id in
 the form of a URL argument string along these lines:
 personform.htm?person_id=35.  But it doesn't work when the Python script 
 update_person_py() called by personform.htm itself tries to re-call
 personform.htm, trusting the hidden field to convey the person_id data.
 Instead, the data update is performed but the next thing the browser shows
 is an AttributeError=person_id.  The body of the update_person_py script
 is:
 
 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')

the redirect above when the script is included like 
you shown, causes the header: location: to be set.
Then Zope outputs all the HTML from ZPT and the
browser reads the location: header and makes a
new request with the URL found there. This 
new request obviously misses all the form information.


 What's wrong with this picture?

I'd use the controller-script approach here.
This is, you have the python script, which
checks the REQUEST for form information
and perhaps initialize some variables with
default data.

value=context.REQUEST.get('value',default) 
is the pattern here.

You would check for the name of the submit button
or some essential form data.

Depending on action, do your updates in database
or whatever.

Next read data out of database. Usually you connect
this to a preparation of data for the template. 
The pattern is like this:

somedata=[{'value1':r.value1,  # use comments a lot
   'value2':r.value2,  # possibly in every
   'value3':r.value3+r.value4  # line

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

2005-05-18 Thread Ken Winter
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:[EMAIL PROTECTED]
 Sent: Wednesday, May 11, 2005 5:52 PM
 To: [EMAIL PROTECTED]
 Cc: zope@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:[EMAIL PROTECTED]
 Sent: Wednesday, May 11, 2005 4:27 PM
 To: [EMAIL PROTECTED]
 Cc: zope@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.
 

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

2005-05-18 Thread Paul Winkler
On Wed, May 18, 2005 at 07:32:29PM -0400, Ken Winter wrote:
 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.

You can append it to the url as a query parameter.
e.g.:

response.redirect('some_page?some_parameter=%s' % some_value)
 
-- 

Paul Winkler
http://www.slinkp.com
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists - 
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


Re: [Zope] How to make a ZPT-based form that calls itself?

2005-05-11 Thread J Cameron Cooper
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...
table width=100% height=100% border=0 cellpadding=6
cellspacing=0
  tr 
td width=1084 height=531 align=left valign=topfont
color=#00 face=Verdana, Arial, Helvetica, sans-serif!--
InstanceBeginEditable name=Base --
  h1 People (deletion test)/h1
  table tal:repeat=row here/dbobs/read_all_people width=100%
border=0 cellspacing=0 cellpadding=0font face=Verdana, Arial,
Helvetica, sans-serif
tr 
  td width=44% tal:content=string:${row/person_id} -
${row/first_name} ${row/middle_names} ${row/last_name}Filler/td
  td width=56%nbsp;/td
/tr
  /table
  p/p
  form action=dbobs/delete_person_py method=post
name=delete_form
pId of Person To Delete: 
  input type=text name=person_id:int /
/p
p 
  input name=do_delete type=submit id=do_delete value=Delete
this Person /
/p
  /form
  pThe quot;Idsquot; are the numbers in front of each person's
name./p
  pa href=deltest.htmRefresh This Page/a/p
  p tal:replace=python:here.dbobs.test1('MyParamValue')Junk/p	
  !-- InstanceEndEditable --/font/td
  /tr
/table

...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')
In your case, since this is a destructive method, you probably want do a 
redirect, back to your listing.

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.)

		--jcc
--
Building Websites with Plone
http://plonebook.packtpub.com/
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists - 
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope-dev )


RE: [Zope] How to make a ZPT-based form that calls itself?

2005-05-11 Thread Ken Winter
 -Original Message-
 From: J Cameron Cooper [mailto:[EMAIL PROTECTED]
 Sent: Wednesday, May 11, 2005 4:27 PM
 To: [EMAIL PROTECTED]
 Cc: zope@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...
 
  table width=100% height=100% border=0 cellpadding=6
  cellspacing=0
tr
  td width=1084 height=531 align=left valign=topfont
  color=#00 face=Verdana, Arial, Helvetica, sans-serif!--
  InstanceBeginEditable name=Base --
h1 People (deletion test)/h1
table tal:repeat=row here/dbobs/read_all_people width=100%
  border=0 cellspacing=0 cellpadding=0font face=Verdana, Arial,
  Helvetica, sans-serif
  tr
td width=44% tal:content=string:${row/person_id} -
  ${row/first_name} ${row/middle_names} ${row/last_name}Filler/td
td width=56%nbsp;/td
  /tr
/table
p/p
form action=dbobs/delete_person_py method=post
  name=delete_form
  pId of Person To Delete:
input type=text name=person_id:int /
  /p
  p
input name=do_delete type=submit id=do_delete
 value=Delete
  this Person /
  /p
/form
pThe quot;Idsquot; are the numbers in front of each person's
  name./p
pa href=deltest.htmRefresh This Page/a/p
p tal:replace=python:here.dbobs.test1('MyParamValue')Junk/p
 
!-- InstanceEndEditable --/font/td
/tr
  /table
 
  ...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?

 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?  Why in that case is a redirect better?

 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?

Anyway, thanks so much for getting me over this hurdle!

- Ken


___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


Re: [Zope] How to make a ZPT-based form that calls itself?

2005-05-11 Thread Phillip Hutchings
  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()

Of course it didn't, there's no object called deltest and the object
that's not there certainly doesn't have a method called htm. Think
about Python syntax - the . delimits a class containment hierarchy.
Zope allows you to have the . in object names, which I disagree with,
so you have to use getattr(context, 'deltext.htm')() to get the actual
object.

-- 
Phillip Hutchings
http://www.sitharus.com/
[EMAIL PROTECTED] / [EMAIL PROTECTED]
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists -
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )


Re: [Zope] How to make a ZPT-based form that calls itself?

2005-05-11 Thread J Cameron Cooper
Ken Winter wrote:
-Original Message-
From: J Cameron Cooper [mailto:[EMAIL PROTECTED]
Sent: Wednesday, May 11, 2005 4:27 PM
To: [EMAIL PROTECTED]
Cc: zope@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/
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists - 
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope-dev )


Re: [Zope] How to make a ZPT-based form that calls itself?

2005-05-11 Thread Paul Winkler
On Wed, May 11, 2005 at 04:51:33PM -0500, J Cameron Cooper wrote:
 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.

But note that they're not semantically equivalent.
getattr(foo, 'bar')  might use acquisition to find 'bar'.
foo['bar'] does not use acquisition, it only looks directly in foo.

I don't like this difference, but, whatever.

-- 

Paul Winkler
http://www.slinkp.com
___
Zope maillist  -  Zope@zope.org
http://mail.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists - 
 http://mail.zope.org/mailman/listinfo/zope-announce
 http://mail.zope.org/mailman/listinfo/zope-dev )