[Twisted-Python] Woven: access to submodels

Donovan Preston dp at twistedmatrix.com
Sat Jul 19 15:08:35 EDT 2003

I apologize for not responding immediately.

On Saturday, July 12, 2003, at 7:21PM, Mary wrote:

> I'm trying to replicate the functionality of http://eyes.puzzling.org/
> (currently powered by a bunch of Python CGI scripts running on an 
> Apache
> webserver) in Woven.
> eyes.puzzling.org is a kind of a minimalist blog, with pages that list
> recent entries, the authors of the entries, and so on.

Cool! Have you seen Blog, in the twistedmatrix.com cvs? It is out of 
date and
needs work, but feel free to steal the code/take over the 


> For each author, I would like to generate a /author/AUTHORNAME/ page
> which lists their individual entries. I am trying to create these pages
> from AuthorsPage's getDynamicChild method. The idea is to pass the
> already constructed submodel -- a dictionary representing the 
> individual
> author -- to the IndividualPage object I will construct to represent 
> the
> individual author's page, rather than have IndividualPage make its own
> database query for that information.

That's good -- that sounds like a good design. There are no rules when 
comes to Woven architecture, but reusing your Model objects, and model
production logic, across multiple pages sounds like a good idea to me.

> At present, as you can see below, I'm using getSubmodel to retrieve
> the (dictionary) submodel associated with a particular author. However,
> this returns a twisted.web.woven.model.DeferredWrapper instance, rather
> than the dictionary itself. Should I make IndividualPage add callbacks
> to the DeferredWrapper, or am I missing something crucial about
> retrieving submodels or is this model more fundamentally incorrect?

As Moshe said in his reply, currently the URL traversal process is 
so if you need to wait on a Deferred to construct the next URL segment 
you're going to be doing a lot more work than you should have to. Woven 
to hide Deferreds from the programmer by pausing rendering and resuming 
when the Deferred fires. So, fortunately, things may be simpler than 
they seem.
You can just pass the DeferredWrapper as the Main Model to the next Page
instance you construct, and as long as you are going to be rendering 
that Page
next, Woven will just wait on it as it would any other Deferred.

from twisted.web.woven import page
from twisted.web.woven import model

from twisted.internet import defer
from twisted.internet import reactor

class DeferredProducer(model.MethodModel):
     def wmfactory_someDeferred(self, reqeuest):
         d = defer.Deferred()
         reactor.callLater(0.5, self.produce, d)
         return d

     def produce(self, d):
         d.callback( "Hello, here is some text" )

     def wmfactory_someNotDeferred(self, request):
         return "Hi there"

class MainPage(page.Page):
     template = """<html>
     <h3 model="someNotDeferred" view="Text">qawsf</h3>
     <span model="someDeferred" view="Text">qwensd</span>

     def getDynamicChild(self, name, request):
         return ChildPage(
                     self.model.getSubmodel(request, 'someDeferred'))

class ChildPage(page.Page):
     template = """<html>
     Hello! Our main model is a deferred, so the next node will have to 
     <span model="." view="Text">ncxnz</span>

resource = MainPage(DeferredProducer())

More information about the Twisted-Python mailing list