[Zope] Argument passing and DTMLFile methods

Terry Hancock hancock@anansispaceworks.com
Sun, 30 Jun 2002 08:01:27 -0700


Dieter Maurer wrote:
> Terry Hancock writes:
>  > ....
>  > EXCEPT... :-(
>  >
>  > This only works if I use *implicit* dtml-var substitutions,
>  > like:
>  >
>  > <dtml-var mydtml_submethod>
>  >
>  > If I try to use the explicit form mentioned above,
>  >
>  > <dtml-var expr="mydtml_submethod(_.None, _)">
>  >
>  > I lose my context!
> In a Python method context, this looks like
> 
>             mydtml_submethod(self, self.REQUEST, keyword_parameters)

Okay, I guess this would work from a Python method (I
haven't tried that yet -- though I suppose I could write
a wrapper that way -- call the python method, then call
the DTMLFile method -- but then I'd lose my context there
too, I think, since Python doesn't support the implicit
passing that DTML does).

>From another DTMLFile method, though, as in:

<dtml-var expr="mydtml_submethod(self,self.REQUEST,
keywordparm=keywordval)">

this gives the same unfortunate results I had with passing "_.None, _"
(just tested it).

For the "client", I've since tried "this, _.this, _.this(), context,
'context'".  All seem to have the same effect (actually _.this()
generates
an error indicating that _.this isn't callable -- sort of a relief,
since it proved I was actually having some effect!).

I also tried changing the DTMLFile from a class method to
an instance method. I.e. changing from:

class my_class(Folder):
	mydtml_method = DTMLFile('dtml/mydtml_method', globals())
	mydtml_submethod = DTMLFile('dtml/mydtml_submethod', globals())

to

class my_class(Folder):
	def __init__(self):
		self.mydtml_method = DTMLFile('dtml/mydtml_method', globals())
		self.mydtml_submethod = DTMLFile('dtml/mydtml_submethod', globals())


But this doesn't seem to work. I wonder if this actually
makes any difference, since presumeably the class methods
are inherited by the instance anyway.  (I think it does
mean I have to recreate the object to allow changes to take
effect -- I'm not certain I verified this to be true, though
I do re-create the object just to be sure).

Also, I still don't really understand what I'm doing
here -- for example, where exactly *is* the caller's
namespace in this example?

I've called an object method through the web:

HTTP_REQUEST --> my_object.mydtml_method

Then that method is calling another method on the same
object:

my_object.mydtml_method --> my_object.mydtml_submethod

So, is the client "my_object"?  Does this mean that the
DTML names are in "my_object"'s __dict__ (or something
equivalent to that?).

I can't really refer to the object explicitly, since I
would need to know the instance name. (I'm sure there's
a round-about way to do it, if I think about it hard
enough).

The thing that baffles me, is that:

<dtml-let keywordparm=keywordval>
	<dtml-var mydtml_submethod>
</dtml-let>

works just fine (I've tested it several times).  I guess
that'll be my work-around if I can't figure out how
to do it "right", but the problem makes me think I
don't understand what I'm doing and might well shoot
myself in the foot.

Also, it's clear that Zope somehow *can* do what I
want, since it does it for the implicit case.

I've been trying to sort out the DTML processing code,
following the traceback, which is, as I said, pretty
hairy to read.

It DOES appear that a "DTMLFile method" is indeed a
different beast than either "DTML Method" or
"DTML Document", and an underdocumented one -- a search
for "DTMLFile" on www.zope.org turns up depressingly
few references, and most of those are to using it for
manage_add<product>Form methods.

I know that the "globals()" call in the DTMLFile()
constructor call is needed to find the correct location
of the file -- does it do anything else?  Can one set
the client in the constructor call (or am I doing that
by making it a method of the class or the class instance?).

I made a sample product for this problem, which is at the
URL below. As is, it doesn't work -- you have to alter
the commented-out lines in "dtml/test_form_dtml" to
see the "correct" output (just look for the <dtml-comment>
element -- it's pretty obvious actually):

http://www.anansispaceworks.com/Download/TestProduct.tgz

Any comments on this example would be appreciated.

> http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html

And thanks for the book reference, Dieter (earlier
in the DTML arguments thread that preceded this) -- is
that your manuscript for Wrox?  It looks pretty good so far.

Looking at the section in there on calling "DTML Objects",
I notice that it says that for "DTML Methods" there is
no client, but that the caller's names are passed in the
REQUEST.

Am I barking up the wrong tree then? Is it the REQUEST
variable that I'm getting wrong?  

Oh, I just found out one more thing -- if I change the
web REQUEST to:

...my_class/mydtml_method?implicitvar=override

Then the value "override" will be passed to mydtml_submethod,
and the call succeeds!  In other words, passing "_" is passing
the REQUEST but not the namespace within mydtml_method.

Does *that* mean anything to anyone?

Well, I'm still thrashing around quite a bit -- not
sure what sort of problem I have yet, so any suggestions
would be appreciated.

Thanks!
Terry

-- 
------------------------------------------------------
Terry Hancock
hancock@anansispaceworks.com       
Anansi Spaceworks                 
http://www.anansispaceworks.com 
P.O. Box 60583                     
Pasadena, CA 91116-6583
------------------------------------------------------