Questions re: REQUEST, external methods; newbie stupidity at play
Greetings: I realize I am likely doing stuff in the cruftiest way possible: Rather than flame if you have the urge, a link to specifics on better ways to do what I am doing would be appreciated. I have a set of external methods that do some stuff to create and build an XML document. I am also doing a lot of logic in DTML and passing stuff back and forth to these external methods. A great simplification of what I am doing: ---------------------- <dtml-call expr="REQUEST.set('myxmldoc',createxmldoc())"> <!-- createxmldoc is an external method that creates a (minidom) Document() and adds a root node. They are returned as a tuple, i.e. myxmldoc[0] will be the xml doc object and myxmldoc[1] will be the node--> <!-- dtml logic that gets some info from a database --> <dtml-call expr="REQUEST.set('myxmldoc',addanode(myxmldoc[0],myxmldoc[1],databasevar)"> <!-- in the line above, databasevar is some info from my DB, and addanode is an external method... --> ---------------------- The problem is, that when I do this, re-using the myxmldoc var causes a __getitem__ attribute error. I have to use a new name, i.e. modxmldoc, to get around the error. OK, I thought, fine, so long as I can kill the original myxmldoc object, as I have many iterations of this and I do not want to end up with a huge amount of objects in memory, getting larger and larger. However, I can't figure out how to 'unset' myxmldoc - setting it to '' doesn't work, I get a string index out of range error. If I specifically set myxmldoc[0] and myxmldoc[1] to '', that works, but I still get the __getitem__ error when I attempt to re-use the variable. Suggestions? TIA, Bryan
Here's what you're trying to do: <dtml-call "REQUEST.set('some_var', some_function())"> <dtml-call "REQUEST.set('some_var', some_other_function(some_var))"> That's not going to work. Unlike Python, DTML doesn't seem to like using a variable in an expression whose output is stored in the same variable. Maybe somebody smarter could offer an explanation why not. Anyway... what you want to do is: <dtml-call "REQUEST.set('some_var', some_function())"> <dtml-call "REQUEST.set('some_temp', some_var)"> <dtml-call "REQUEST.set('some_var', some_other_function(some_temp))"> Sad but true... unless there's a better workaround I don't know about. HTH, Dylan On Tue, 2003-07-15 at 12:35, zoper@disturbance.dhs.org wrote:
Greetings:
I realize I am likely doing stuff in the cruftiest way possible: Rather than flame if you have the urge, a link to specifics on better ways to do what I am doing would be appreciated.
I have a set of external methods that do some stuff to create and build an XML document. I am also doing a lot of logic in DTML and passing stuff back and forth to these external methods. A great simplification of what I am doing:
---------------------- <dtml-call expr="REQUEST.set('myxmldoc',createxmldoc())"> <!-- createxmldoc is an external method that creates a (minidom) Document() and adds a root node. They are returned as a tuple, i.e. myxmldoc[0] will be the xml doc object and myxmldoc[1] will be the node-->
<!-- dtml logic that gets some info from a database -->
<dtml-call expr="REQUEST.set('myxmldoc',addanode(myxmldoc[0],myxmldoc[1],databasevar)"> <!-- in the line above, databasevar is some info from my DB, and addanode is an external method... --> ----------------------
The problem is, that when I do this, re-using the myxmldoc var causes a __getitem__ attribute error. I have to use a new name, i.e. modxmldoc, to get around the error.
OK, I thought, fine, so long as I can kill the original myxmldoc object, as I have many iterations of this and I do not want to end up with a huge amount of objects in memory, getting larger and larger. However, I can't figure out how to 'unset' myxmldoc - setting it to '' doesn't work, I get a string index out of range error. If I specifically set myxmldoc[0] and myxmldoc[1] to '', that works, but I still get the __getitem__ error when I attempt to re-use the variable.
Suggestions?
TIA, Bryan
_______________________________________________ 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 )
OK, well your answer also touches on another issue that I sent to the list a few days previously - 'Freeing ZSQL Result Sets'. Essentially, I have a loop in which I need to use the same SQL queries repeatedly with different values in the where clause. I end up having to have several exact duplicate ZSQL: queries with different names in order to avoid problems. So, though I think Dylan has answered this question as "no" in the response below, I simplify my question to: Can you / how does one destroy variables / objects in DTML? Bryan Dylan Reinhardt wrote:
Here's what you're trying to do:
<dtml-call "REQUEST.set('some_var', some_function())"> <dtml-call "REQUEST.set('some_var', some_other_function(some_var))">
That's not going to work. Unlike Python, DTML doesn't seem to like using a variable in an expression whose output is stored in the same variable. Maybe somebody smarter could offer an explanation why not.
Anyway... what you want to do is:
<dtml-call "REQUEST.set('some_var', some_function())"> <dtml-call "REQUEST.set('some_temp', some_var)"> <dtml-call "REQUEST.set('some_var', some_other_function(some_temp))">
Sad but true... unless there's a better workaround I don't know about.
Bryan White wrote:
Can you / how does one destroy variables / objects in DTML?
It isn't generally done, but that doesn't mean it can't be. Take for example the manage_tabs.dtml from the ZMI. I rewrote mine a while back to fix a host of annoyances including the leak of some its "temporary" variables it uses into all other tabbed ZMI pages. That particular DTMLFile uses the variable a_ via a REQUEST.set('a_', ...) to hold the sequence index of the currently active tab, at the end of that file, rather than let the value of a_ leak into all the following dtml manage_tabs is called from, I do: <dtml-comment>don't leak a_</dtml-comment> <dtml-if manage_options><dtml-call "REQUEST.other.__delitem__('a_')"></dtml-if> It helps to understand how HTTPRequest objects really work, and exactly what calling .set() does, and how and when keys of the request object are promoted between the various dictionaries that make up their internal storage. The real zen is avoiding the need for ever using .set() at all. -- Jamie Heilman http://audible.transient.net/~jamie/ "I was in love once -- a Sinclair ZX-81. People said, "No, Holly, she's not for you." She was cheap, she was stupid and she wouldn't load -- well, not for me, anyway." -Holly
Jamie wrote: "The real zen is avoiding the need for ever using .set() at all." Yes. This perhaps gets at the heart of the big concept that I think I must be missing. I have a SQL-heavy application, that makes heavy use of both DTML and external methods (instead of script due to the need to import xml.* stuff). How do I build a stack of variables to pass around between ZSQL -> DTML -> Py *without* having a giant mess of REQUEST.set statements? I can easily believe that I have missed some totally fundamental thing, but as it stands I have an insane amount of REQUEST.set stuff in this project. I have actually begun to lament that I chose to go with Zope on this particular project (don't get me wrong - I am a near-religous Zope advocate) - this project is not about content management in the least, it's a big beast of a SQL / XML monster. Zope oddities have been more in my way than they have been helpful. Again, I am perfectly willing to believe that I am simply doing things WRONG. The only big win I get from Zope on this project so far is users/roles, and not having to code that stuff. Please, what is the correct way to NOT use the REQUEST space like I am??? Desperately, Bryan
On Thu, 2003-07-17 at 11:39, Bryan White wrote:
How do I build a stack of variables to pass around between ZSQL -> DTML -> Py *without* having a giant mess of REQUEST.set statements?
I can easily believe that I have missed some totally fundamental thing, but as it stands I have an insane amount of REQUEST.set stuff in this project.
At the risk of suggesting something obvious, have you read the docs? http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/RelationalDataba... http://www.zope.org/Documentation/Guides/ZSQL-HTML/ZSQL.html I suspect what you're missing is that you're trying to re-create stuff that Zope already does for you. Only in specific cases is explicit "passing" required. I don't sense that yours is one of them. Dylan
At the risk of suggesting something obvious, have you read the docs?
http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/RelationalDataba... http://www.zope.org/Documentation/Guides/ZSQL-HTML/ZSQL.html
I suspect what you're missing is that you're trying to re-create stuff that Zope already does for you. Only in specific cases is explicit "passing" required. I don't sense that yours is one of them.
Actually, I am positively drowning in the docs, which is part of the problem. Between the official Zope docs, the "Book of Zope" from Beehive, and the tons of informal user-created documentation on the net, there are no less than 50 answers for any question. Thanks for the explicit links rather than just a blind 'RTFM', for sure, though. I suspect my bad habits are coming from my scripty background rather than anything else. I am spoiled by creating and discarding variables arbitrarily in basically procedural code. So, if I have a mess like: 1. Some DTML stuff to make logical decisions 2. Some unrelated stuff 3. Some more DTML that depends on the decisions made in step 1 In order to find out the result of the decisions made in step 1 when I am in step 3, I want to look at the value of some variables. As far as I can tell the only way to keep track of the stuff is in REQUEST. I am, in fact, calling my ZSQL methods with parameters and only in once case relying on REQUEST for that (userid in the database of the current user, using exUserFolder). It's the fact that I am acutally using DTML for a lot of core logic that I am using REQUEST. <dtml-let> absolutely will not work for me as the variables need to span a bunch of <dtml-in> and <dtml-if> blocks. Reading my own responses in the thread here, I realize that I am showing myself to be a complete noob who probably shouldn't be even allowed to use the py interpreter. Hrmph. Thanks for the insight, all.
On Thu, 2003-07-17 at 13:04, Bryan White wrote:
I suspect my bad habits are coming from my scripty background rather than anything else. I am spoiled by creating and discarding variables arbitrarily in basically procedural code. So, if I have a mess like:
1. Some DTML stuff to make logical decisions 2. Some unrelated stuff 3. Some more DTML that depends on the decisions made in step 1
The Zope way is more like this: 1. Use objects to store and retrieve data. 2. Use Python (scripts or ext. methods) for logic 3. Use ZPT or DTML to obtain results from 1 or 2 and display them 4. Use acquisition to integrate 1-3 DTML and TAL have logical constructs, but this shouldn't be confused with them being good tools for actual logic. The heaviest logic you should probably be doing with templates is iterating over result sets and determining how/if results should be displayed. Ex: <UL> <dtml-in some_sequence prefix=my_seq> <dtml-if my_seq_item> <!-- my_seq_item is non-False / non-empty --> <LI><dtml-var my_seq_item></LI> </dtml-if> </dtml-in> </UL> Note that some_sequence (your result set) is probably the id of some other object such as a script, external method or ZSQL method. Although it *could* be a variable you set earlier in DTML, that's a less common usage. Typically, you use Python and/or ZSQL to do any heavy lifting required to *create* a result set and to use templating for little more than obtaining & formatting the results. As a variation, what if you *do* have to pass something to get the proper result set? You'll have something like this: <dtml-in "some_sequence(name)"> Where 'name' has some obtainable value in the current context. Assuming that the 'some_sequence' object can accept this argument, it will do whatever it's supposed to do and return a result set for the DTML to iterate over & format. That's 99% of all there is to it. I hope that helps you over the conceptual hump. Zope is much harder to use when you don't buy into the way it's designed to be used. If at all possible, I'd suggest ditching the procedural/scripty approach. HTH, Dylan
Bryan White wrote:
In order to find out the result of the decisions made in step 1 when I am in step 3, I want to look at the value of some variables. As far as I can tell the only way to keep track of the stuff is in REQUEST.
Nope, you can also use judiciously placed dtml-let's
using exUserFolder). It's the fact that I am acutally using DTML for a lot of core logic that I am using REQUEST.
You really should be using Python Scripts or external methods for this...
<dtml-let> absolutely will not work for me as the variables need to span a bunch of <dtml-in> and <dtml-if> blocks.
What leads you to believe that -let won't work in these cases? cheers, Chris
Bryan White wrote:
I have actually begun to lament that I chose to go with Zope on this particular project (don't get me wrong - I am a near-religous Zope advocate) - this project is not about content management in the least, it's a big beast of a SQL / XML monster. Zope oddities have been more in my way than they have been helpful. Again, I am perfectly willing to believe that I am simply doing things WRONG. The only big win I get from Zope on this project so far is users/roles, and not having to code that stuff.
Me too. The security model of Zope is one of its great features. Maybe I am missing something. I've gone through the line of posts, but I still don't understand why you can't do the entire thing in on External Method. This lets you do all the work in Python, and avoid the idiosyncracies of REQUEST.set; but you still get REQUEST when you need it -- to get data *from* the client and to return the results. Or maybe I am missing something crucial? Is it the ZSQL calls that "require" goign back and forth from EMs to DTML? JZ
On Thu, 17 Jul 2003 14:52:24 -0500 John Ziniti <jziniti@speakeasy.org> wrote:
Bryan White wrote:
I have actually begun to lament that I chose to go with Zope on this
particular project (don't get me wrong - I am a near-religous Zope advocate) - this project is not about content management in the least, it's a big beast of a SQL / XML monster. Zope oddities have been more in my way than they have been helpful. Again, I am perfectly willing to believe that I am simply doing things WRONG. The only big win I get from Zope on this project so far is users/roles, and not having to code that stuff.
Me too. The security model of Zope is one of its great features. Maybe I am missing something. I've gone through the line of posts, but I still don't understand why you can't do the entire thing in on External Method.
This lets you do all the work in Python, and avoid the idiosyncracies of REQUEST.set; but you still get REQUEST when you need it -- to get data *from* the client and to return the results.
Or maybe I am missing something crucial? Is it the ZSQL calls that "require" goign back and forth from EMs to DTML?
JZ
You can work in DTML, ZPT, Script python, or external methods. Any do fine. If you work in pythonic methods, then you are making some trade-offs. You have to understand the result-set returned by ZSQL. See http://www.zope.org/Members/spinwing/ZSQL_Results. You are responsible for digging out name to column references yourself. There are two basic ways of doing it -- hardwiring it, and this (script python syntax, which I would prefer to external methods wherever possible): res=container.my_sql_query(parameter1=value1, p2=v2, ...) names=res.names() n2i={} for i in range(len(names)): n2i[names[i]]=i Then you can refer to the i'th row with column name foo as res[i][n2i['foo']] You can also mix models and pass the request in as the parameter to the query. I would discourage that. If you want to go this route, be explicit, and give actual parameters. Jim Penny
_______________________________________________ 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 )
John Ziniti wrote:
Or maybe I am missing something crucial? Is it the ZSQL calls that "require" goign back and forth from EMs to DTML?
Well, in my case I am using DTML as a crutch, because initially it seemed very fast / easy to prototype a lot of logic there. Bryan
Bryan White wrote:
John Ziniti wrote:
Or maybe I am missing something crucial? Is it the ZSQL calls that "require" goign back and forth from EMs to DTML?
Well, in my case I am using DTML as a crutch, because initially it seemed very fast / easy to prototype a lot of logic there.
And thereby hangs a cautionary tale.... I'd suggest looking at having the 'process' as an External Method which calls ZSQL Methods as needed... cheers, Chris
Dylan Reinhardt wrote at 2003-7-15 16:21 -0700:
<dtml-call "REQUEST.set('some_var', some_function())"> <dtml-call "REQUEST.set('some_var', some_other_function(some_var))">
That's not going to work. Unlike Python, DTML doesn't seem to like using a variable in an expression whose output is stored in the same variable.
I do not believe this: "REQUEST.set" is a normal Python function. Calling it, first evaluates the arguments and only then enters the function body. However, I remember faintly, that there was a DTML namespace caching issue. Under some circumstances the value read from "REQUEST" was cached and later delivered from the cache rather than freshly read from "REQUEST". Dieter
On Wed, 2003-07-16 at 12:30, Dieter Maurer wrote:
Dylan Reinhardt wrote at 2003-7-15 16:21 -0700:
That's not going to work. Unlike Python, DTML doesn't seem to like using a variable in an expression whose output is stored in the same variable.
I do not believe this:
"REQUEST.set" is a normal Python function. Calling it, first evaluates the arguments and only then enters the function body.
That makes sense. Even so, I have encountered the exact problem the OP described. Perhaps he and I are committing the same error, but the effects he described were instantly familiar to me. I don't use REQUEST.set() much any more, so I could be remembering my difficulties incorrectly.
However, I remember faintly, that there was a DTML namespace caching issue. Under some circumstances the value read from "REQUEST" was cached and later delivered from the cache rather than freshly read from "REQUEST".
Is this the cause of the OP's problem, you think? Dylan
Dylan Reinhardt wrote at 2003-7-16 16:03 -0700:
...
However, I remember faintly, that there was a DTML namespace caching issue. Under some circumstances the value read from "REQUEST" was cached and later delivered from the cache rather than freshly read from "REQUEST".
Is this the cause of the OP's problem, you think?
Too much time has passed when I analysed this caching problem. Maybe, the mailing list archives still helds the post. Search for "Dieter REQUEST cached" (maybe "cached" replaced by "caching", "cache" or something similar). Dieter
Dylan Reinhardt wrote:
Here's what you're trying to do:
<dtml-call "REQUEST.set('some_var', some_function())"> <dtml-call "REQUEST.set('some_var', some_other_function(some_var))">
That's not going to work. Unlike Python, DTML doesn't seem to like using a variable in an expression whose output is stored in the same variable. Maybe somebody smarter could offer an explanation why not.
Don't really see why not... But then, when would you want a construct like the above? cheers, Chris
participants (8)
-
Bryan White -
Chris Withers -
Dieter Maurer -
Dylan Reinhardt -
Jamie Heilman -
Jim Penny -
John Ziniti -
zoper@disturbance.dhs.org