[Twisted-Python] domtemplate examples
Hey all, Does anyone have more involved examples (even ones they can only share privately for now) of using DOMTemplate than the one in doc/howto? Examples of form integration and DB integration like outputting lists of things from a result set of a query would all be welcome. - Bruce
I got around to solving this today for doing DB integration with webMVC: Bruce Mitchener wrote:
Does anyone have more involved examples (even ones they can only share privately for now) of using DOMTemplate than the one in doc/howto?
Examples of form integration and DB integration like outputting lists of things from a result set of a query would all be welcome.
The patch below makes the standard domwidgets.List friendly for Deferreds. Similar things need to be done to the other widgets as well if that's the path that should be taken. This code sucks for various reasons, but actually works: class MIdentityList(wmvc.WModel): def __init__(self): self.dbpool = adbapi.ConnectionPool('pyPgSQL.PgSQL', 'localhost', 'bruce', 'XXXXXXXXX', database='XXXXXXXXX') self.dbauth = authorizer.Authorizer(self.dbpool) self.identityList = self.getIdentities() def setIdentities(self, result): self.identityList = result def getIdentities(self): return self.dbauth.getIdentities().addCallback(self.setIdentities) class IdentityListWidget(domwidgets.Widget): def generateDOM(self, request, node): """ Generate DOM to represent a list of identities. """ if isinstance(self.model.identityList, defer.Deferred): return self.identityList self.add(domwidgets.List()) return domwidgets.Widget.generateDOM(self, request, node) class VIdentityList(wmvc.WView): templateFile = "identity_list.xhtml" def factory_identityList(self, request, node): return IdentityListWidget(self.model) class CIdentityList(wmvc.WController): pass wmvc.registerViewForModel(VIdentityList, MIdentityList) Am I doing anything that is horribly wrong (apart from obvious things, like not grabbing a service and starting up the authorizer inside of the model), and that isn't likely to work beyond a simple test case like this? I do like how the Deferreds integrate in with the DOMTemplate and webMVC stuff. Pretty nice work, once I figured it out. :) - Bruce Index: domwidgets.py =================================================================== RCS file: /cvs/Twisted/twisted/web/domwidgets.py,v retrieving revision 1.19 diff -u -r1.19 domwidgets.py --- domwidgets.py 19 Aug 2002 03:22:01 -0000 1.19 +++ domwidgets.py 13 Sep 2002 18:13:59 -0000 @@ -3,6 +3,7 @@ import urllib from xml.dom.minidom import parseString +from twisted.internet import defer from twisted.python.mvc import View, Model from twisted.python import domhelpers, log @@ -262,11 +263,14 @@ """ tagName = None def generateDOM(self, request, node): + data = self.getData() + if isinstance(data, defer.Deferred): + return data.addCallback(self._cbGenerateDOM, request, node) node = Widget.generateDOM(self, request, node) # xxx with this implementation all elements of the list must use the same view widget listItem = domhelpers.get(node, 'listItem') domhelpers.clearNode(node) - for itemNum in range(len(self.getData())): + for itemNum in range(len(data)): # theory: by appending copies of the li node # each node will be handled once we exit from # here because handleNode will then recurse into @@ -277,6 +281,10 @@ domhelpers.superPrependAttribute(newNode, 'model', self.submodel + '[' + str(itemNum) + ']') node.appendChild(newNode) return node + + def _cbGenerateDOM(self, result, request, node): + return self.generateDOM(request, node) + class ColumnList(List): def __init__(self, model, columns=1, start=0, end=0):
Bruce, Your code totally rocks, and I liked it so much I abstracted it to apply to all Widgets, automatically. Basically, here's how it works; I added a new method to Widget, setUp(self, request, node, data), which gets called before generateDOM. The common case of overriding generateDOM, doing some setup work, and then calling Widget.generateDOM can now be implemented by overriding setUp. As an added bonus, the Model data that the widget is meant to be operating on is passed in to the fourth parameter, data. Then, I changed the way Widgets are rendered so that if a Widget is operating on a subModel which happens to be a Deferred instance, both setUp and generateDOM will be deferred until after the Deferred instance fires. So, you can make a database call in Model.__init__, save the deferred in a subModel, apply a Widget to the subModel, and you don't have to do anything to have your Widget operate correctly. Attached is an example. Thanks for the clarity and inspiration, bruce!
participants (2)
-
Bruce Mitchener
-
Donovan Preston