[TransWarp] More PWT Ideas (usage, not terminology!)

Phillip J. Eby pje at telecommunity.com
Fri Jul 25 09:41:39 EDT 2003

At 11:46 AM 7/25/03 +0200, Roché Compaan wrote:

>What I specifically don't understand is how the heck a DOMlet finds its
>execution context and generally how a WebTraversable, Interaction,
>TemplateDocument and its DOMlets fits together. Conceptually I
>understand what each of these classes should do, but I don't understand
>how these classes connect in the implementation. Some kind of map or
>diagram will help though or maybe just a small DOMlet recipe. This is
>not a call for documentation just some pointers to help me get going
>to make comments on the implementation possible.

TemplateDocument is just another DOMlet, but one that doesn't write a 
beginning or end tag (notice the _openTag = _closeTag = _emptyTag = '' in 
the class definition).  It adds a 'parseFile' method that loads its 
contents.  Apart from those two characteristics, it is just a plain ol' 
DOMlet.  Here's a recipe to make one:

from peak.api import *
from cStringIO import StringIO
root = config.makeRoot()

document = web.TemplateDocument(root)

DOMlets' 'renderFor()' method takes a 'data' item, and a 'state.  The 
'data' item must be an IWebTraversable, so that when you want to go to 
another piece of data, you can traverse to it, with security in 
effect.  Here's a quick recipe to write the above document to stdout:

from peak.web.templates import DOMletState
from sys import stdout
interaction = web.Interaction(root, app=root)
state = DOMletState(root, interaction=interaction, write=stdout.write)

document.renderFor(NOT_FOUND, state)

This should dump out the original XML, so long as it's all representable in 
ASCII (since DOMlets output unicode).  You'll notice I used 'NOT_FOUND' as 
the data; since the sample document doesn't use the data, this is okay.  I 
wanted to make the simplest possible example.  Now, if we need to give 
actual data to the DOMlets, we'll need a traversable, like in 

class Thingy(web.SimpleTraversable):

     security.allow( theVar = [security.Anybody] )

     theVar = "Hello world!"

data = Thingy(root)

document = web.TemplateDocument(root)
document.renderFor(data, state)

This should now output "<something>Hello world!<something>".

If you do this:

print document.children

You'll see that the document has one child DOMlet, a Text DOMlet as 
specified by the input XML.

Is that all a bit clearer now?  test_templates goes a bit further than 
this, as it wants to simulate the conditions when a template is called by 
peak.web as an IWebPage.  So, it makes its subject traversable the 'app' of 
the Interaction, and then traverses from interaction.root to the 'show' 
method, which is where it has stuck the template it's testing.  It then 
uses interaction.callObject(), which adapts the template to IWebPage and 
calls render().  This will invoke the DOMletAsWebPage adapter, whose 
render() method sets up the DOMletState and calls the document's 
'renderFor()' method.

Had this been an actual web application, the interaction would have been 
traversing to 'show' because someone went to the URL '/show' relative to 
the app root, and 'callObject()' would have been invoked by zope.publisher, 
instead of the test's render() method.

Probably, I should add a page template to the "trivial_web" example app, 
but I haven't yet decided on a convention for how to bind a template in a 
class, so I'd have to do it with a Once function, which is pretty 
ugly.  Ultimately I'd like to be able to do something like:

class Something(web.Decorator):

      aMethod = web.bindTemplate('web/SomethingMethod.pwt')

But this needs to be done in such a way that at runtime, the actual 
template is loaded by -- and cached in -- the skin, and can have a 
different definition in each skin.  That part is actually not too 
difficult, it's mostly that I need to decide on the precise rules of how it 
will work and what the defaults for things will be.

More information about the PEAK mailing list