[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)
document.parseFile(StringIO("""<something>whatever</something>"""))
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
test_templates.py:
class Thingy(web.SimpleTraversable):
security.allow( theVar = [security.Anybody] )
theVar = "Hello world!"
data = Thingy(root)
document = web.TemplateDocument(root)
document.parseFile(StringIO("""<something
domlet="text:theVar">whatever</something>"""))
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