is it possible to add numerical comparison test to dtml-in statement ? statement ?
When looping over ZClass instances in a dtml-in statement, I have constantly wanted to add a numerical test condition (eg. "where X > 12" where X is a property of the instance) This applies either using objectValues() to loop over the ZClass instances, or using the ZCatalog. Either way, I end up using something a little retarded like this : <dtml-in "objectValues(['MyClass'])" sort=Points> <dtml-if "Points > 12"> ...... </dtml-if> </dtml-in> or <dtml-in "Catalog({'meta_type': 'MyClass'})" sort=Points> <dtml-if "Points > 12"> ...... </dtml-if> </dtml-in> Either way, it's not ideal b/c it means looping unnecessarily and also, it means that I can't use the very convenient Zope "next/previous" (with a query_start) for long listings. There must be an easy way of incorporating this into the dtml-in statement and I'm ready to eat some humble pie on this one : is it possible ? Mouth wide open, chas
On Sun, Jan 09, 2000 at 02:31:49AM +0800, chas wrote:
When looping over ZClass instances in a dtml-in statement, I have constantly wanted to add a numerical test condition (eg. "where X > 12" where X is a property of the instance) Yep, since <dtml in "foo"> evaluates foo as a Python expression, the following should be possible: <dtml in "_.filter(objectValues(['MyClass'], lamba x: return x > 12)">
filter(alist, func) returns a list of all items in alist for which func returns true. The lamba construct can be used to define a function on the fly, similar to LISP and other functional programming languages. lamba x: return x > 12 is the same as: def afunc(x): return x > 12 -- Stephen Pitts smpitts@midsouth.rr.com webmaster - http://www.mschess.org
Stephen Pitts wrote:
On Sun, Jan 09, 2000 at 02:31:49AM +0800, chas wrote:
When looping over ZClass instances in a dtml-in statement, I have constantly wanted to add a numerical test condition (eg. "where X > 12" where X is a property of the instance) Yep, since <dtml in "foo"> evaluates foo as a Python expression, the following should be possible: <dtml in "_.filter(objectValues(['MyClass'], lamba x: return x > 12)">
Actually, this would be <dtml-in "_.filter(lambda x: x > 12, objectValues(['MyClass']))">. Sadly, DTML does not expose 'filter'. A problem for more even slightly more complicated expressions, although not this one, is that DTML's security features rely on magic variables which aren't accessible to lambda's expression. For example, <dtml-var expr="(lambda x: x.id())(this())"> fails; you have to write <dtml-var expr="(lambda x, _vars=_vars: x.id())(this())">. An External or Python Method could fix this up, or in the given example you could simply write: <dtml-in foo><dtml-if expr="x>12"> ... </dtml-if></dtml-in> This should work fine, as long as you aren't grouping. Cheers, Evan @ 4-am
Actually, this would be <dtml-in "_.filter(lambda x: x > 12, objectValues(['MyClass']))">. Sadly, DTML does not expose 'filter'. You can change that. The list of functions DTML exposes is in lib/python/DocumentTemplate/DT_Util.py, starting at line 214 and continuing until 310. You could easily add all of the functional programming constructs (map, apply, filter) if needed. The beauty of Open Source!
A problem for more even slightly more complicated expressions, although not this one, is that DTML's security features rely on magic variables which aren't accessible to lambda's expression. For example, <dtml-var expr="(lambda x: x.id())(this())"> fails; you have to write <dtml-var expr="(lambda x, _vars=_vars: x.id())(this())">.
Yeah, my DTML is getting pretty ugly. Another option is to use a Python Method to run filter on the list with lamba functions. -- Stephen Pitts smpitts@midsouth.rr.com webmaster - http://www.mschess.org
On Sun, Jan 09, 2000 at 02:31:49AM +0800, chas wrote:
When looping over ZClass instances in a dtml-in statement, I have constantly wanted to add a numerical test condition (eg. "where X > 12" where X is a property of the instance) Yep, since <dtml in "foo"> evaluates foo as a Python expression, the following should be possible: <dtml in "_.filter(objectValues(['MyClass'], lamba x: return x > 12)">
filter(alist, func) returns a list of all items in alist for which func returns true. The lamba construct can be used to define a function on the fly, similar to LISP and other functional programming languages. lamba x: return x > 12 is the same as: def afunc(x): return x > 12
Aaah, very clever :) Thanks indeed, Stephen, for this makes things *much* easier. I was aware of filter() function in python and often use it but I'd never really understood the point of lambda until now. And none of this would have occured to me to use within DTML like that. Thank you again, I'm going to be using this a lot and truly appreciate the clear explanations. chas
participants (3)
-
chas -
Evan Simpson -
Stephen Pitts