I have been aware for some time now that IModel is an interface that is about preparing a model for display in a web browser -- much like Zope3's IView. It converts from whatever raw object interface is present on the original model, to an interface which exposes data suitable for traversal and insertion into a web template file.
So, tonight I went through and added the resource object as the first parameter to lookupSubmodel, getSubmodel, setSubmodel, getData, and setData. Changing the signature of methods which are widely used in a wide variety of situations is painful -- especially when you're changing an interface which is as fundamental to a system as IModel is to woven. However, thanks to the inspect module and some fancy use of positional optional arguments, I was able to come up with a solution that logs DeprecationWarnings whenever a method doesn't expect the request, and passes the request when a method does.
mktap web --path=/path/to/web/files --flashconduit=4321
I'll edit the post below to mention this.
For people who are curious about the bleeding edge of Woven development, I have been working on LivePage a bit more recently. LivePage allows asynchronous events both from the browser, and to the browser after the page has already been loaded. The current implementation in CVS requires Flash, but it is also technically possible to get this to work with an IFrame connection that the server never closes as the Output Conduit. I whipped up a little example so you can get a feel for where I am going with this, and give me feedback if you desire.
If you want to try this, save it as an rpy and view it with twisted.web using a tap created like this: (Latest CVS is probably required)
mktap web --path=/path/to/web/resources --flashconduit 4321
Make sure you put a slash after the .rpy, so the relative urls spit out by the webConduitGlue resolve correctly. For example, http://localhost:8080/simpleLivePageExample.rpy/
from twisted.web.woven import model, page, input, widgets
self.value = 0
def setUp(self, request, node, data):
def clicked(self, request, widget):
self.model.setData(self.model.getData() + 1)
resource = page.LivePage(ANumber())
resource.template = """<html>
<div model="value" view="aView">
<img src="http://www.google.com/images/logo.gif" model="value" view="Widget" controller="aController" />
<div view="webConduitGlue" />