[Zope] a question on external methods

Amos Latteier amos@aracnet.com
Tue, 16 Feb 1999 14:17:05 -0800


At 01:42 PM 2/16/99 -0600, David Wagle wrote:

>def dwName(self,REQUEST=None):
>    return "%s" % REQUEST['AUTHENTICATED_USER']
>
>They both work fine from the Zope/manage screen using the
>'try-it' tab.
...
>When I use them in a test file:
>
><!--#var standard_html_header-->
>
><!--#var test.xm-->
><!--#var test2.xm-->

The problem is a common one.

Invoking a method via a URL is *not* the same as invoking a method by using
the var tag in DTML.

This can be confusing, so let me say it again--the ORB does not call
objects in the same way DTML calls objects.

Invoking a method via a URL is handled by the Zope ORB. It is the process
of object publishing. It involves object traversal rules, argument
marshalling, etc.

Invoking a method via DTML is handled by the DocumentTemplate classes. It
is subject to moderately complex namespace and rendering rules.

In general the ORB will pass arguments to your method when it is published
by looking for them in the HTTP request. In general, DTML will simply call
a method without passing any arguments to it. (Note: DTML Documents and
Methods are an exception to the rule, and are handled specially by both the
ORB and DTML)

DTML is calling your dwName method like this dwName(), while the ORB is
calling it like this dwName(REQUEST=REQUEST).

One solution is to call dwName from DTML like so:

<!--#var "dwName(REQUEST)"-->

Another solution is to not get the REQUEST from the arguments. This way
your method can be called both from DTML and from the ORB.

def dwName(self,REQUEST=None):
    "find the authenticated user"
    if REQUEST is None and hasattr(self,'REQUEST'):
        REQUEST=self.REQUEST
    return "%s" % self.REQUEST['AUTHENTICATED_USER']

This works because Zope makes the current request available as a instance
attribute. (Whoops, another Zope secret comes out ;-)

Hope this helps.

-Amos