[Zope] dtml-var weirdness

Thomas B. Passin tpassin@mitretek.org
Mon, 18 Feb 2002 10:57:01 -0500


[Joseph A Knapka]>
> Stupid question of the day:
>
> Why might the following code result in a KeyError? It does
> in some contexts under Zope 2.5.0.
>
> <dtml-if expr="REQUEST.has_key('xyz')">
> <dtml-else>
>   <dtml-call expr="REQUEST.set('xyz','Hello world')">
> </dtml-if>
>
> Sometimes the next line results in a KeyError, value 'xyz':
>
> <dtml-var name="xyz">
>
> In such cases, this works fine:
>
> <dtml-with REQUEST only>
>   <dtml-var name="xyz">
> </dtml-with>
>

You set the property named "xyz" in the REQUEST, and you can be sure of
referring to it if you say "REQUEST['xyz'] or "REQUEST.xyz", as in

<dtml-var "REQUEST['xyz']">

Note that using "expr=" is redundant - you can always omit it.  So your
example could be written:

 <dtml-if "REQUEST.has_key('xyz')">
   <dtml-else>
       <dtml-call "REQUEST.set('xyz','Hello world')">
 </dtml-if>

or, a bit simpler and more readable,

<dtml-if "not REQUEST.has_key('xyz')">
   <dtml-call "REQUEST.set('xyz','Hello world')">
 </dtml-if>

Referring to "REQUEST['xyz']"  always works.  But as long as no other
namespace has been inserted into the mix, you can also get the value in any
of these ways:

1) <dtml-var "xyz">
2) <dtml-var xyz>
3) <dtml-var "_['xyz']>

That's because REQUEST properties are specially made available to its
owner's namespace for convenience.

These last three versions all really ask for the same thing, just in
slightly different ways:

1) asks for a Python variable named "xyz".  Python looks for this variable
in the namespace stack, which normally starts with the namepace of the dtml
document containing the code (if it is in a dtml document, otherwise
different rules apply).

2) asks Zope for a variable named "xyz".  Zope looks in its namespace stack
to find it.  It's normally the same namespace stack that Python would be
using, so this is equivalent to 1) in most cases.

3) is an alternative way to ask for the same thing as 2).  It's advantage is
that the name of the variable does not have to be known when you write the
code - any string will do.

If the code is in a dtml method, the method does not have its own namespace.
What namespace it uses, and therefore whether it can find the right
variable,  depends on how it is called, thus the results can vary.  There
have been many threads in the list about this.

Cheers,

Tom P