[Zope-dev] Calling DTML methods from Python

Andrew Wilcox circle@gwi.net
Mon, 29 May 2000 14:34:15 -0400


>Is it just me or is there a lot of confusion between the terms
>namespace, self, client, and the REQUEST object (which, unlike it's name
>implies, seems to contain a lot more than stuff relating to the HTTP
>request, like the RESPONSE object, for example ;-)
>
>Perhaps this could be shaken down and then, a first for the Zope
>community I believe ;-), _documented_ somewhere!!!

Well, as far as I've been able to figure out.  But everybody correct me
where I get it wrong:

When a DTML Document is called from the web, it gets itself as the client
argument and a namespace as the second argument.  Note that it gets itself
twice: first as the standard Python object oriented "self" argument and
then as the client argument.

I seem to recall there's some magic in there where the the object is
wrapped in an acquisition class so that it can do a self.REQUEST, but I'm
not sure.

Any DTML methods called by the first object get None passed in as the
client argument.  Importantly, DTML methods do not lookup variables in
themselves (i.e. from the Python "self"), but only from the namespace.  The
original object has been added to the namespace at this point so these
called methods are able to access things.

An example would be if you had a DTML method called "doit" sitting in a
folder next to "standard_html_header".  Because doit acquires from its
container, you could say "doit.standard_html_header" from Python because
standard_html_header is a property of the containing folder.  But using
"<dtml-var standard_html_header>" from inside doit only works if
standard_html_header is available in the namespace.

External methods add more fun :-).  As noted in the documentation, the
enclosing folder will be passed in automatically if you call the first
argument "self" (and you pass in yourself one fewer argument than the
function calls for).  Note this is NOT the standard python object oriented
"self" argument, which would be the external method sitting in the ZODB if
anything, but the enclosing folder.  You do have to call it "self" or you
don't get anything.  The "self" argument is able to acquire REQUEST so you
can say "self.REQUEST", but you don't get a namespace automatically.