Hi everyone. I'm somewhat new to Zope, so I have what may be a stupidly simple problem (probably is, actually). I want to have a site that allows adding, editing & searching of various database tables (eg. people). To keep things consistent for the user, I'd like to use one page template that has all the fields, and just call that template with an add dtml method, an edit dtml method, and a search dtml method. The part I'm having difficulty with is the connection between the ZSql and the template - specifically, I execute a SQL function to get the person's data, and I'd like to populate the template with it. To do this, I need to set the 'value' field of each input type in the form. I can set the field values in the form like this: <tr> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value request/form/first_name" tal:on-error="string:"> </td> </tr> This works if the form has itself as an action target. But what is the namespace for the variables returned by a ZSQL call? The column has the same name as the field (in this case, 'first_name'). How do I access the returned values from an ZSQL call? Another thing I've been wondering - I can't find the documentation on the various namespaces (here, request, etc). Where are they listed, and when should you use one over the other? TIA, Colin -- Colin Fox cfox@crystalcherry.com CF Consulting Inc. GPG Fingerprint: D8F0 84E7 E7CC 5C6C 9982 F1A7 A3EB 6EA3 BC97 572F
Colin Fox wrote:
This works if the form has itself as an action target. But what is the namespace for the variables returned by a ZSQL call? The column has the same name as the field (in this case, 'first_name'). How do I access the returned values from an ZSQL call?
A ZSQL Method call returns a list of dictionaries (at least to dtml), each dictionary { 'colname':colvalue } just like a table in Python (details: http://www.zope.org/Members/spinwing/ZSQL_Results and sourcecode). In Python, access as myresult[nr_of_row]['name_of_col'] to get a single value. ------------------------------------------------------------- Who's got only a hammer sees the world as a nail hans augustin (software developer) hans@beehive.de beehive elektronische medien GmbH http://www.beehive.de phone: +49 30 847-82 0 fax: +49 30 847-82 299
I want to have a site that allows adding, editing & searching of various database tables (eg. people).
To keep things consistent for the user, I'd like to use one page template that has all the fields, and just call that template with an add dtml method, an edit dtml method, and a search dtml method.
The part I'm having difficulty with is the connection between the ZSql and the template - specifically, I execute a SQL function to get the person's data, and I'd like to populate the template with it. To do this, I need to set the 'value' field of each input type in the form.
Well, you need to execute the ZSQL method obviously, and you can do this more than one way: One way to do it is to call it in a Script (python) and pass the information by the request namespace: Script (python) =============== data = context.your_sql([param=value]) #assuming you returned 1 row context.REQUEST.set('field', data[0]['colname']) return context.your_template(context) then <tr> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value request/field" tal:on-error="string:"> </td> </tr> but this is messy and requires an extra file.... it makes more sense to me to call it in your template: Page Template ============= (might have to massage the param/value part if it's needed; get it from request or some other way) <table tal:define="data python:here.your_sql([param=value])"> <tr tal:repeat="items data"> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value items/colname" tal:on-error="string:"> </td> </tr> </table> There are probably other ways as well but I'd use method #2. Hope this helps. -- Jeffrey D. Peterson Webmaster & Resident Standards Warrior "The Trouble with doing anything right the first time is that nobody appreciates how difficult it was."
On Tue, 2002-03-26 at 08:29, Jeff Peterson wrote: <snip>
it makes more sense to me to call it in your template:
Page Template ============= (might have to massage the param/value part if it's needed; get it from request or some other way)
<table tal:define="data python:here.your_sql([param=value])"> <tr tal:repeat="items data"> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value items/colname" tal:on-error="string:"> </td> </tr> </table>
The problem with this, though, is that I don't want to call the database in my template. I want the template to be re-used by 3 different DTML methods: add, edit & search. When adding and searching, I'm not executing a database query until the user hits the submit button. But in the case of 'edit', I'm passing the personid that I want to edit, so the edit dtml method executes the query and then invokes the template. Here's what my edit method looks like (it's invoked with the parameters "?personid=x"): <dtml-var standard_html_header> <h2><dtml-var title_or_id> <dtml-var document_title></h2> <dtml-in expr="get_customer(pid=personid)"> <form action="&dtml-URL0;" method="post"> <input type="hidden" name="personid" value=<dtml-var personid> > <dtml-var genericform_html> </form> </dtml-in> <dtml-var standard_html_footer> I know that the form submission is wrong - that I'll need an intermediate script to rewrite the data back into the tables. But right now I'm just trying to populate the form with the values from the query. It seems to me that this is an appropriate thing for templates. Is there a better way to do this (re-usable forms)? -- Colin Fox cfox@crystalcherry.com CF Consulting Inc. GPG Fingerprint: D8F0 84E7 E7CC 5C6C 9982 F1A7 A3EB 6EA3 BC97 572F
-----Original Message----- From: Colin Fox [mailto:cfox@crystalcherry.com] Sent: Tuesday, March 26, 2002 2:43 PM To: jpeterso@rangebroadband.com Cc: zope@zope.org Subject: RE: [Zope] ZPT, DTML, SQL and Forms
On Tue, 2002-03-26 at 08:29, Jeff Peterson wrote: <snip>
it makes more sense to me to call it in your template:
Page Template ============= (might have to massage the param/value part if it's needed; get it from request or some other way)
<table tal:define="data python:here.your_sql([param=value])"> <tr tal:repeat="items data"> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value items/colname" tal:on-error="string:"> </td> </tr> </table>
The problem with this, though, is that I don't want to call the database in my template. I want the template to be re-used by 3 different DTML methods: add, edit & search. When adding and searching, I'm not executing a database query until the user hits the submit button. But in the case of 'edit', I'm passing the personid that I want to edit, so the edit dtml method executes the query and then invokes the template.
Here's what my edit method looks like (it's invoked with the parameters "?personid=x"):
<dtml-var standard_html_header> <h2><dtml-var title_or_id> <dtml-var document_title></h2>
<dtml-in expr="get_customer(pid=personid)"> <form action="&dtml-URL0;" method="post"> <input type="hidden" name="personid" value=<dtml-var personid> > <dtml-var genericform_html> </form> </dtml-in>
<dtml-var standard_html_footer>
You have 4 choices I can see: 1) use a different form template for when you need to populate the form. 2) Use the same form and conditionalize the sql based on what you are doing like: Add to your dtml: <input type="hidden" name="edit" value="1"> <div tal:condition="python: request.edit == '1'"> <table tal:define="data python:here.your_sql([param=value])"> <tr tal:repeat="items data"> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value items/colname" tal:on-error="string:"> </td> </tr> </table> </div> <div tal:condition="python: request.edit != '1'"> <table> <tr> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name"></td> </tr> </table> </div> 3) Use the Script (python) I showed you before, setting the values into the request namespace. 4) If you are using Page Template you can put the form function in a macro and use one template but make the conditional call the macro based on what you want to do. I'd choose either the Macro method or make a separate template. Ive used the latter o great success. -- Jeffrey D. Peterson Webmaster & Resident Standards Warrior "The Trouble with doing anything right the first time is that nobody appreciates how difficult it was."
On Tue, 2002-03-26 at 08:29, Jeff Peterson wrote: <...>
Well, you need to execute the ZSQL method obviously, and you can do this more than one way:
One way to do it is to call it in a Script (python) and pass the information by the request namespace:
Script (python) ===============
data = context.your_sql([param=value]) #assuming you returned 1 row context.REQUEST.set('field', data[0]['colname']) return context.your_template(context)
then
<tr> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value request/field" tal:on-error="string:"> </td> </tr>
Thanks Jeff - this got me going again. I've decided to go this route, because it keeps the template very simple. My script ended up being: res = context.get_customer(personid=pid) d = res.dictionaries()[0] for k in d.keys(): context.REQUEST.set(k, d[k]) Since the column names are (intentionally) the same as the input field names, I can get away with just using they key values. Now that I think of it, this script is quite generic, except for the call to get_customer(). I'm going to have at least 2 more add/edit/seach sections within my site, and I'm going to end up copying all this stuff and just renaming one function call. It would be great if I could call this "populate" or something, and just pass the name of the sql query to execute. I'm not sure how to do this in Zope (in Python, I could just create a function object to execute, but I don't know if that's possible in zope, or if so, what the semantics are). I have an allergy to cutting/pasting code and only changing one thing. I'd really like to parameterize as much as possible. Any ideas? -- Colin Fox cfox@crystalcherry.com CF Consulting Inc. GPG Fingerprint: D8F0 84E7 E7CC 5C6C 9982 F1A7 A3EB 6EA3 BC97 572F
Off the top of my head you could pass a parameter to the script which describes the action you wish to proceed with and then do an if/then kind of thing on the possible sql queries, this is hackish but would work. I would have to do some looking to figure out a slicker way and unfortunately I am out of time for today. If I come up with a better way I'll let you know. Glad I could help some anyway, -- Jeffrey D. Peterson Webmaster & Resident Standards Warrior "The Trouble with doing anything right the first time is that nobody appreciates how difficult it was."
-----Original Message----- From: Colin Fox [mailto:cfox@crystalcherry.com] Sent: Tuesday, March 26, 2002 5:30 PM To: jpeterso@rangebroadband.com Cc: zope@zope.org Subject: RE: [Zope] ZPT, DTML, SQL and Forms
On Tue, 2002-03-26 at 08:29, Jeff Peterson wrote: <...>
Well, you need to execute the ZSQL method obviously, and you can do this more than one way:
One way to do it is to call it in a Script (python) and pass the information by the request namespace:
Script (python) ===============
data = context.your_sql([param=value]) #assuming you returned 1 row context.REQUEST.set('field', data[0]['colname']) return context.your_template(context)
then
<tr> <td><LABEL for="firstname">First name: </LABEL></td> <td><INPUT type="text" name="first_name" value="" tal:attributes="value request/field" tal:on-error="string:"> </td> </tr>
Thanks Jeff - this got me going again. I've decided to go this route, because it keeps the template very simple. My script ended up being:
res = context.get_customer(personid=pid) d = res.dictionaries()[0] for k in d.keys(): context.REQUEST.set(k, d[k])
Since the column names are (intentionally) the same as the input field names, I can get away with just using they key values.
Now that I think of it, this script is quite generic, except for the call to get_customer(). I'm going to have at least 2 more add/edit/seach sections within my site, and I'm going to end up copying all this stuff and just renaming one function call.
It would be great if I could call this "populate" or something, and just pass the name of the sql query to execute. I'm not sure how to do this in Zope (in Python, I could just create a function object to execute, but I don't know if that's possible in zope, or if so, what the semantics are).
I have an allergy to cutting/pasting code and only changing one thing. I'd really like to parameterize as much as possible.
Any ideas?
-- Colin Fox cfox@crystalcherry.com CF Consulting Inc. GPG Fingerprint: D8F0 84E7 E7CC 5C6C 9982 F1A7 A3EB 6EA3 BC97 572F
participants (3)
-
Colin Fox -
hans -
Jeff Peterson