[Zope] Testing multiple values for existance - still

Paul Winkler slinkp23@yahoo.com
Tue, 25 Sep 2001 13:42:49 -0400


On Tue, Sep 25, 2001 at 11:54:33AM +0200, Oliver Sturm wrote:
> On 25.09.2001 10:24:48 -0400 Phil Harris <phil.harris@zope.co.uk> wrote:
> > The first statement tests first for existence, and only then for value.
> > The second assumes existence and only tests for value.
> 
> I got that at last :-). But WHY? I reckon it may be as simple as that the
> "'s render the whole thing a Python expression instead of something that can
> be handled directly by Zope. Is that so? 

Exactly. Inside a dtml tag, anything in quotes is treated as python code.

> If yes, I'd consider that a large
> drawback and inconsistency... and does Python syntax for the test have to be
> so complicated?

It's not "complicated" in normal python programming, which is usually
easy, flexible, and powerful. But when you're limited to what you can
fit between quotes in a dtml tag, you can't really take advantage of
python effectively. It was never meant to be a language for
one-liners.

But of course, we have python scripts and external methods, which are
much better for jobs like this. 

If all you want is to know if any of a bunch of zope objects exist in
this folder, or if any of some properties has a true value, it's ugly
and hard to read if you do it in the dtml-if tag:

<dtml-if "(_.hasattr('foo') and foo) or (_.hasattr('bar') and bar)">

... and it just gets worse if you want to test for more names!
So I'd make a python script like this:

## Script (Python) "check_for_any"
##bind container=container
##bind context=context
##bind script=script
##bind subpath=traverse_subpath
##parameters=*args
##title=
##
found = None

for a in args:
   try:
       x=getattr(context, a)
       if x:
            found = 1
            break      # Jump out of the loop, no more tests needed
   except AttributeError:
       continue

return found


The key thing to notice is that the one argument is *args.  In python,
that means that this function takes a variable number of arguments,
and they will be stored in a list of the given name (in this case,
args).

Now you can do this in your dtml:

<p>Checking for one thing...

<dtml-if "check_for_any('foo')">
  ...
</dtml-if>

<p>Checking for more things...

<dtml-if "check_for_any('foo', 'bar', 'baz', 'bat', 'baf')">
  ... 
</dtml-if>


Much nicer, eh?

-- 
................    paul winkler   ................
 custom calendars:   http://www.calendargalaxy.com
   A member of ARMS:   http://www.reacharms.com
        home page:  http://www.slinkp.com