[Zope] render/parse function ? (using <dtml-var x> in a propertysheet ?)sheet ?)

Michel Pelletier michel@digicool.com
Sat, 08 Apr 2000 22:06:51 -0700


chas wrote:
> 
> >How is this different than just creating a string property called
> >'FirstName' and:
> >
> >Hello <dtml-var FirstName>
> >
> >instead of <dtml-var myproperty>?
 
<snip translation requriments>

This might be a bit too complex for DTML, you might want to try it all
as a Python product, some kind of object that translates for you...  
 
> Ah, I assume to mean Graham Chiu's earlier message, to which
> you replied :
> 
> [snip]
> 
> Uhm... I don't know.  What you want to turn your string into is an
> object that can evaluate DTML code, then you can call it from another
> tag such as var or call or in.  This cannot be done from DTML, you need
> to drop to python to do this.  Just instanciate a 'temporary' DTML
> object (proabably a method), feed it your string, and then call it.
> This could probably be done easily from an external method:
> 
> <dtml-var "anExternalMethod("<dtml-var blah>")">
> 
> [/snip]
> 
> OK. Thanks also to John Earl also for pointing me in the
> right direction on this one. The following sort of works:
> 
> An external method 'externalRenderer' contains the following :
> 
> from OFS.DTMLMethod import DTMLMethod
> def renderstring(str, REQUEST):
>     m = DTMLMethod(str, REQUEST)
>     return m()
> 
> This works if the variable exists in the REQUEST object :
> 
> eg. <dtml-call "REQUEST.set('x', 'Silly')">
>     <dtml-var "externalRenderer('Hello <dtml-var x> World', REQUEST)">
>     will display 'Hello Silly World'
> 
> BUT if you have an image object called 'myimg' that is
> normally accessible with <dtml-var myimg>, you have to
> first force it into the REQUEST method :
> 
> eg. <dtml-call "REQUEST.set('myimg', myimg)">
>     <dtml-var "renderme('Hello <dtml-var myimg> World', REQUEST)">
> 
> Which sort of defeats the purpose.

The reason this does not work is that the current Acquisition namespace
is not available to 'm'.  Neither is the DTML namespace.  The only
namespace you've provided for it is REQUEST.

You'll need to make two changes, first, pass the current container
(self) in as the client object, and pass the DTML namespace into the
exernal method seperatly, like this:

from OFS.DTMLMethod import DTMLMethod

def renderstring(self, str, ns={}, REQUEST=None):
    m = DTMLMethod(str, REQUEST)
    return m(self, ns)

Note how self is passed in, this is the current _Acquisition wrapped_
container that this method was called from.  Notice also the new
argument ns that defaults to an empty dictionary.  I've defaulted
REQUEST to None because it's a good habit.

When m is called, a 'client' is passed, self, and a namespace.  So now
acquisition works with no changes, and if you want to pass in the DTML
namespace use '_'

Just Acquisition
<dtml-var "externalRenderer('Hello <dtml-var myimg> World')">

Acquisition and DTML
<dtml-var "externalRenderer('Hello <dtml-var myimg> World', _)">

I don't think you need to pass REQUEST in, it should be passed for you
because it's in the external method signature.

Untested.

> >Perhaps you could think up some more interesting use cases than what you
> >have here and put them on the InterfaceWishList:
> >
> >http://www.zope.org/Members/michel/Projects/Interfaces/
> 
> Took a look - seems to go in circles... keep the UI guy away from LSD.

It'll become second nature to you.  After a while, you'll wonder how you
lived without Wiki.

-Michel