[Zope-dev] Help, please!!! __call__ problems with DTML templates

Stephen Simmons stephen.simmons@healtharena.net
Tue, 10 Oct 2000 17:41:34 +0200


Today is not a good day:-(     I've just spent 2 days trying to force
__call__ to render my product properly, got every error possible at least
seven times, and wasted last night working out what was wrong with Refresh
(I was calling refresh on the wrong product. Duh!).

Please, please, please, can someone point me in the right direction.

I have a class called Element which has three components:
1. purpose: a string describing the element's role (rendered as structured
text)
2. template: a string that is rendered to display the element (DTML)
3. Element inherits from Folder so it can contain sub-elements which can be
included in the template

For example, suppose A is an element that contains a sub-element B (i.e. B
is A.B)
  A    has template 'Element A contains <dtml-var B>'
         and purpose 'Contain B'
  B    has template 'element B, which contains nix'
        and purpose 'Element with no subelement'

Now for the tricky bit: "<dtml-var A>" needs to be rendered one of three
possible ways depending on a variable in the REQUEST. So __call__ needs to
return one of
- case a:  the purpose property (as structured text) wrapped in []
- case b:  render the template, with sub-elements properly rendered
- case c:  render the template, with sub-elements wrapped in [] showing
their purpose

Then '<dtml-var A>' must be rendered in the three cases as:
 - case a:  '[Contain B]'
 - case b:  'Element A contains element B, which contains nix'
 - case c:  'Element A contains [Element with no subelement]'

To do this, I need to write my own __call__ method since __call__ is what
detemines how objects gets rendered in DTML (is this correct?)
     def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
With this, I discovered that '<dtml-var A>' gives client=None and REQUEST={}
while
'<dtml-var "A(_,REQUEST)">' gets client=_ and REQUEST=REQUEST.

But I cannot for the life of me, work out how to do what I need. In
particular:

1.)  How do you magically get the DTML context from '<dtml-var A>' without
having to resort to '<dtml-var "A(_,REQUEST)">' in the templates?

In the __call__ methods of different classes, I've seen some code like:
        'if REQUEST is None and not kw: REQUEST=self.REQUEST' (from
Catalog.py)
and other code like
        'if hasattr(self, 'aq_explicit'): bself=self.aq_explicit  else:
bself=self' and
        'security=getSecurityManager()       security.addContext(self)'
(from DTMLDocument.py)
I can't see any consistency in what these classes are doing, so I don't know
what I need to do.

2.)  How to convert an arbitrary text string into rendered DTML inside a
python product method?
How do you get the object's properties, REQUEST and acquisition context all
in the namespace?

I've been trying code like:
   template = '<span class="purpose"><dtml-var purpose
fmt="structured_text"></span>'
   dtml = HTML(template, globals())
   rendered = dtml(self, REQUEST)
but this doesn't work. All the example classes I've seen (such as
ZWikiPage.py in ZWiki) use DTMLDocument as their base class so can call
DTMLDocument's __call__ on themselves as in
    text = apply(DTMLDocument.__call__,(self, client, REQUEST, RESPONSE),
kw)    (ZWikiPage.py, line 135)
This doesn't help me because I don't have DTMLDocument as a base class.
Looking through the source for DTMLMethod etc is not very clear because lots
of "apply(__call__,(...),kw)" calls are all mixed up with acquisition code.

3.)  Do I need to write a custom tag (<dtml-element A>) to get this
behaviour?

So, if anyone out in Zope land can help me, I'll be eternally grateful. I've
exhausted my patience looking through the NIP mailing list archives, the
How-Tos and the Zope site and need to have something to demonstrate on
Thursday.

Thanks in advace,

Stephen

P.S.  ChrisW, searching NIP for "__call__" returns every message with 'call'
in it, which is not quite the same thing!
_______________________________
Stephen Simmons
HealthArena B.V.
phone +31 20 486 0555
mobile +31 6 1505 3086
stephen.simmons@healtharena.net