[Zope] Re: [Zope-dev] Missunderstanding of DTML Methods and acquisition?

Michel Pelletier michel@digicool.com
Sat, 11 Mar 2000 12:26:36 -0800


This thread is more appropriate for the main list.  zope-dev is for
development topics.

"R. David Murray" wrote:
> 
> I'm finding this to be one of the trickiest "simple bits" of dtml to
> learn, even after having read the docs.  The following should work
> in your /user/regions/index_html (tested):
> 
> <dtml-var IManager>
> 
> As you may already know, the following will instead get you quoted
> text of the IManage method:
> 
> <dtml-var "IManager">
> 
> The following will also work (tested):
> 
> <dtml-var "IManager(_.None,_)">
> 
> This passes a 'client' of None and the namespace (that img exists
> in) to the method.  (I presume that in the first working example above
> Zope supplies the client and namespace to the method when it evaluates
> it). 

Correct.

> This call form is of course what you'll need if you want to
> pass arguments to the method:
> 
> <dtml-var "IManager(_.None,_,somearg='someval')">
> 
> What I'm most confused about right now is when it is necessary to pass
> the client and namespace and when you can omit it. 

It is necessary when you want to call a DTML Method or Document from a
Python expression and you want that DTML Method or Document to be able
to look things up as an attribute of a 'client' or in your current
namespace (or any namespace you provide).  You can omit it when you are
using a DTML Method or Document _by name_ in DTML.  Note that:

<dtml-var IManager>

is the same as:

<dtml-var name="IManager">

and:

<dtml-var "IManager()">

is the same as:

<dtml-var expr="IManager()">

So most people use the first and third shorthand forms to use an object
by name and to execute a python expression respectivly.  When the DTML
Engine sees that you are using an object by name, it tries to do clever
things, like detect if it is a DTML object and to call the method and
pass the namespace 'magically'.

When the DTML engine sees that you are using an expression, it assumes
you know what you are doing and does no magic for you.  Therefore, you
must explicitly pass in the namespace.

> I'm also very unclear
> as to just what the 'client' is, especially since most of the examples
> I've seen involve passing in None for the client.

The 'client' is an object that you want to use as a namespace.  For
example, if DTML Method 'IManager' wants to find the name 'img' you can
pass a client object, and the method will try and do a getattr(client,
name) (in this case, name being 'img').  If you pass a namespace, then
it will try and do a namespace[name].  If neither of these succeed, it
will look for the name in the optional list of keyword arguments you can
provide.  If that fails, it raises a NameError.

The reason why it is None in most cases is because you want your method
to look things up using the Zope DTML Namespace (affectionately known as
'_').  In some special case however, you may want to explicitly provide
some other object.

This is single handedly the #1 obfusication in Zope and the most
frequently asked question.  We, of course, did not obfusicate this on
purpose.  When DTML was first concieved it worked by name only, so the
behind the scenes magic was acceptable and intuitive.  Later, we added
python expressions, and the ugliness of calling DTML Methods and
Documents became aparent.

-Michel