Hello all, I've been getting into Twisted apps recently and saw in the docs that use of Woven is not recommended and that Nevow should be used instead. Thats cool. I've been trying to get into it, and have read lots of docs and examples, but its seriously hard going. I'm not trying to dump on anyone, but the examples don't start out with really simple building blocks then build on that into something big and usable as-is. Something I can say "I need to do a multistage form - ah theres an example", and "I need to store user sessions in a persistent way, so they're there after a database restart - ah an example..." etc. That is, start with really really basic apps, adding extra details and features that someone will commonly want. For example, it might start with a really simple html template example, using minimal Nevow stuff - just a renderer or at most a page, and everything else from Twisted. Maybe this isn't the "done" thing, but I think it would be really helpful to someone coming from now understanding Twisted classes to see how to use a minimal set of Nevow classes to do something cool with Nevow. I would've thought Nevow would work well in this way, but tell me if I'm wrong and I should really be using the whole Nevow framework, not just the xhtml templating part. Right now I want to use my own Site object, not a subclass of the Nevow site object, and use the Nevow classes to generate html based on templates from files. I'm sure this is possible, but I just can't figure it out. So, here is my question... I have this in a file "hello_template.html": <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <title nevow:data="title">This is title</title> </head> <body> <p>This page is called <span nevow:date="title" /></p> </body> </html> and I have the following python code. The function demo1() does what I expect, but what I really want is for demo2() to print to stdout the xhtml after it has been substituted with the title. << from nevow import rend class HelloPage(rend.Page): docFactory = rend.htmlfile('hello_template.html') def data_title(self, context, data): return "Hello Nevow World" def data_empty(self, context, data): return [] def someMethodToWriteToAFileLikeObject( self, writer ): writer.write( "not yet implemented\n" ) def demo1( ): """This will print the html just as it is in the template file - cool""" import sys d = rend.htmlfile('hello_template.html', '../shared/Assets/template') d.load() print "\nDocument:\n" d.getDoc( ).writexml(sys.stdout) print "\n" def demo2( ): """This does not work yet, but what I want it to do, is put the substituted title into the template then return the composite result. """ import sys p = HelloPage( ) p.someMethodToWriteToAFileLikeObject( sys.stdout ) if __name__ == "__main__": demo1( ) demo2( )
I know that in normal usage there isn't much point doing sys.stdout.write with the xhtml content, but there has to be some room between that extreme and using a framework where I can't even tell how the content is getting sent back to the http stream! Thanks to all for any suggestions, and for your patience with this beginner... Ellers
On Sun, 2004-04-04 at 17:06, Ellers wrote:
Right now I want to use my own Site object, not a subclass of the Nevow site object, and use the Nevow classes to generate html based on templates from files.
Why in particular don't you want to use NevowSite? You don't need to subclass NevowSite, it can be used as-is (see the attached example).
I have this in a file "hello_template.html":
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <title nevow:data="title">This is title</title> </head> <body> <p>This page is called <span nevow:date="title" /></p> </body> </html>
Nevow did away with one major headache of Woven: it doesn't try to guess a suitable renderer for a particular piece of data. So if you say, <title nevow:data="title" nevow:render="string">Something</title> Then this will work normally. If you only assign a data attribute, but no render attribute, nothing happens. One alternative is to write your own renderers, by making render_foo methods instead of data_foo methods. These must return something that is itself renderable, like a string, list, or a stan tag. I've attached a slight reworking of your example. You can run this normally, or you can run it with 'twistd -ony example1.tac.py' to actually start a web server. It shows both how to use data_ and render_ methods, and also answers your question about rendering pages into plain text strings. Hope this helps. -- Alex Levy WWW: http://mesozoic.geecs.org "Never let your sense of morals prevent you from doing what is right." -- Salvor Hardin, Isaac Asimov's _Foundation_
Hey Alex,
Thanks for your help - thats awesome.
More comments below...
On Sun, 04 Apr 2004 20:10:08 -0400, Alex Levy
On Sun, 2004-04-04 at 17:06, Ellers wrote:
Right now I want to use my own Site object, not a subclass of the Nevow site object, and use the Nevow classes to generate html based on templates from files.
Why in particular don't you want to use NevowSite? You don't need to subclass NevowSite, it can be used as-is (see the attached example).
thats a good question. Primarily my logic is that I shouldn't "have" to use a NevowSite. The twisted framework is, well, quite a heavy framework as it is. I have my existing (admittedly somewhat lame) resource.Resource subclasses, and I felt that I "should" be able to use Nevow without having to do everything its way (ie using NevowSite). Hope that doesn't sound too militant... I guess I figure Nevow sounds like a great opportunity for a cool API, but I'm hoping I don't have to use it as a heavyweight framework. Where the difference between API and framework is how locked in I am to do my code "its way". WDYT?
I have this in a file "hello_template.html":
(snip)
I've attached a slight reworking of your example. You can run this normally, or you can run it with 'twistd -ony example1.tac.py' to actually start a web server. It shows both how to use data_ and render_ methods, and also answers your question about rendering pages into plain text strings.
Hope this helps.
it does - thanks! The core of what you sent is this part: def printPage(): p = HelloPage() # Ordinarily this remembering nonsense is done for us. p.remember(p, inevow.IData) p.remember(p, inevow.IRendererFactory) # Rend.Page.renderString() returns a deferred, so... def gotRenderedPage(html): print print 'Page:' print html p.renderString().addCallback(gotRenderedPage) Nifty trick with the deferred and the gotRenderedPage() callback. I'm still having trouble getting my mind around deferred so thats helpful. Can you expand a bit on how the remember() calls are helpful? I use interfaces a lot generally (though usually thats C++ or Java), but I don't quite get how they're useful in this case? thanks for any tips :) Ellers
On Mon, 2004-04-05 at 14:24, Ellers wrote:
Why in particular don't you want to use NevowSite? You don't need to subclass NevowSite, it can be used as-is (see the attached example).
thats a good question.
Primarily my logic is that I shouldn't "have" to use a NevowSite. The twisted framework is, well, quite a heavy framework as it is. I have my existing (admittedly somewhat lame) resource.Resource subclasses, and I felt that I "should" be able to use Nevow without having to do everything its way (ie using NevowSite).
Hope that doesn't sound too militant... I guess I figure Nevow sounds like a great opportunity for a cool API, but I'm hoping I don't have to use it as a heavyweight framework. Where the difference between API and framework is how locked in I am to do my code "its way".
Have you tried using NevowSite, but giving it one of your custom resources instead of a nevow.rend.Page instance? I'm not sure whether that will work or not, but I don't see why it shouldn't. NevowSite is just a subclass of t.w.server.Site, which you need anyways. The main thing about NevowSite is that it converts everything to inevow.IResource instead of t.w.resource.IResource. This means support for both "old" resources, like yours, and for Nevow's own resources. So you're getting more by usingi t, and there's very little additional overhead.
Nifty trick with the deferred and the gotRenderedPage() callback. I'm still having trouble getting my mind around deferred so thats helpful.
You'll see deferreds all over Twisted. They're very useful, sometimes essential, in a framework where you don't always know everything at once.
Can you expand a bit on how the remember() calls are helpful?
They're essential. Normally they get called in Page.renderHTTP, but they aren't there in renderString. (Anyone, is this a bug? Is there a reason they're not in renderString?) -- Alex Levy WWW: http://mesozoic.geecs.org "Never let your sense of morals prevent you from doing what is right." -- Salvor Hardin, Isaac Asimov's _Foundation_
Have you tried using NevowSite, but giving it one of your custom resources instead of a nevow.rend.Page instance? I'm not sure whether that will work or not, but I don't see why it shouldn't. NevowSite is just a subclass of t.w.server.Site, which you need anyways.
That works nicely, thanks :) I'll keep experimenting there and tinker with things to get a better understanding of how the parts work together. In the meantime, I'm having trouble with lists now - in particular, I want to display a list and have each item be a link. I looked at the Nevow calendar example but I can't follow it. In my page class I have this (excerpt): def data_names(self, context, data): # this is a list of strings return self.names def getURLForName( self, name ): # a crappy demo of how I can parameterise getting the URL # for a given name return "/data/%s" % name def render_link(self, context, data): # would it be better to do something like: # # return T.a(href=url)[title], # # ? # name = ?? url = self.getURLForName( name ) return "<a href='%s'>%s</a>" % ( url, title ) I know this code isn't great, but the thing I'm stuck on right now is how do I get the name argument - from the data parameter? Oh, and I probably shouldn't be calling it render_link... sorry guys, I get lost with Nevow a bit! :) The html fragment I'm using is: <p>This is called <span nevow:data="title" nevow:render="string" /></p> <p>This is a list of stuff:<br/> <ol nevow:data="names" nevow:render="sequence"> <span nevow:pattern="header">HEADER</span> <li nevow:pattern="item"><span nevow:render="string" /></li> <span nevow:pattern="divider">-----</span> <div nevow:pattern="empty">Nothing.</div> <span nevow:pattern="footer">FOOTER</span> </ol> </p> The title span is working really well - and many thanks here go to Alex Levy! thanks for any help on the above Ellers
On Wed, 2004-04-07 at 21:28, Ellers wrote: [snip]
I'm having trouble with lists now - in particular, I want to display a list and have each item be a link. I looked at the Nevow calendar example but I can't follow it.
In my page class I have this (excerpt):
def data_names(self, context, data): # this is a list of strings return self.names
def getURLForName( self, name ): # a crappy demo of how I can parameterise getting the URL # for a given name return "/data/%s" % name
def render_link(self, context, data): # would it be better to do something like: # # return T.a(href=url)[title], # # ? # name = ?? url = self.getURLForName( name ) return "<a href='%s'>%s</a>" % ( url, title )
I know this code isn't great, but the thing I'm stuck on right now is how do I get the name argument - from the data parameter?
The sequence renderer causes each item in the sequence to be passed to the renderer as the data arg. So in your code "name = data" would work. Although ... you don't appear to be calling the "link" renderer from the HTML template you included, it's calling the standard string renderer still. Creating the HTML fragment and returning it from render_link() is a bad idea as the string will be xml-escaped, i.e. '<' will be replaced with '<', '>' will be replaced with '>', etc. You should definitely use the stan tags in this case, in fact the "return T.a ..." in the comment is spot on. NOTE: If you really, really want to send some HTML in a string then wrap it in a tags.xml object which will pass the string straight through. For instance, i.e. return T.xml("<a href='%s'>%s</a>" % ( url, title )).
Oh, and I probably shouldn't be calling it render_link... sorry guys, I get lost with Nevow a bit! :)
The html fragment I'm using is:
<p>This is called <span nevow:data="title" nevow:render="string" /></p> <p>This is a list of stuff:<br/> <ol nevow:data="names" nevow:render="sequence"> <span nevow:pattern="header">HEADER</span> <li nevow:pattern="item"><span nevow:render="string" /></li>
<span nevow:pattern="divider">-----</span> <div nevow:pattern="empty">Nothing.</div> <span nevow:pattern="footer">FOOTER</span> </ol> </p>
The title span is working really well - and many thanks here go to Alex Levy!
I'll let you have a crack at getting things working now but you may also want to look at the nevow.url module. It makes constructing URLs *really* easy. Hope this helps. Cheers, Matt -- __ / \__ Matt Goodall, Pollenation Internet Ltd \__/ \ w: http://www.pollenation.net __/ \__/ e: matt@pollenation.net / \__/ \ t: +44 (0)113 2252500 \__/ \__/ / \ Any views expressed are my own and do not necessarily \__/ reflect the views of my employer.
I'd like to write a messageboard-like website/application in twisted. I've been going through the Calendar example from nevow.com, and the bannerfish example from itamarst.org - trying to get an understanding to begin with. I was hoping that someone on this list could point me to some more examples that I can learn from -- everything that I've seen so far has focused on one or two pages, and I'm trying to figure out how to have multiple page types and more info. Thanks
On Apr 8, 2004, at 3:20 PM, Jonathan Vanasco wrote:
I'd like to write a messageboard-like website/application in twisted.
I've been going through the Calendar example from nevow.com, and the bannerfish example from itamarst.org - trying to get an understanding to begin with.
I was hoping that someone on this list could point me to some more examples that I can learn from -- everything that I've seen so far has focused on one or two pages, and I'm trying to figure out how to have multiple page types and more info.
The ultimate example of using nevow is Quotient. Unfortunately, it's probably not the easiest to follow. To orient you should you decide to look at the code, all URLs are expressed in the form /me/123 where 123 is the unique identifier of an object in a database. The database is 'atop', an object database, so attempting to visit that page will load the corresponding object from the DB. Then, an IResource adapter is located for that object. So, you can look at any of the IResource adapters (registered in webcomponents.wsv) for examples of multiple Page types. For some simpler examples, the apps which come to mind are Matt Goodall's pastebin, and Alex Levy's CMS (does it have a name?). Perhaps they could share some code or links. As always, please drop by #twisted.web on irc.freenode.net and ask questions freely. There is a high likelihood that someone will be happy to answer your questions and have a technical discussion with you. If nobody answers immediately, idle for a couple of hours... someone should answer eventually :-) dp
I'd like to write a messageboard-like website/application in twisted.
[snip]
I was hoping that someone on this list could point me to some more examples that I can learn from -- everything that I've seen so far has focused on one or two pages, and I'm trying to figure out how to have multiple page types and more info.
The ultimate example of using nevow is Quotient. Unfortunately, it's probably not the easiest to follow.
I think it would be awesome to have a directory of examples that build up from crawling, to walking then running with twisted/nevow. Twisted/nevow is something much more powerful than, say, Perl's CGI.pm but that package is very easy to learn, to see what it can do, how to use it, etc. Examples using CGI.pm are at: http://stein.cshl.org/WWW/software/CGI/examples/ Aside from being great for beginners, there is another great benefit to lots of small and medium examples. A framework built for one application tends can be a bit myopic. If there are lots of little examples, each showing how to do one element cleanly and clearly, the framework will probably need to bend a little (or a lot!) and everyone will benefit. I'm still a beginner with Twisted/Nevow and, if I can figure it out, I'd love to contribute some examples. In the meantime I want to flag it as something that would be cool and worth the effort. And again thanks to everyone who has been helping me with my queries so far :) Ellers
On Fri, 2004-04-09 at 09:49, Ellers wrote:
I'd like to write a messageboard-like website/application in twisted.
[snip]
I was hoping that someone on this list could point me to some more examples that I can learn from -- everything that I've seen so far has focused on one or two pages, and I'm trying to figure out how to have multiple page types and more info.
The ultimate example of using nevow is Quotient. Unfortunately, it's probably not the easiest to follow.
I think it would be awesome to have a directory of examples that build up from crawling, to walking then running with twisted/nevow. Twisted/nevow is something much more powerful than, say, Perl's CGI.pm but that package is very easy to learn, to see what it can do, how to use it, etc. Examples using CGI.pm are at: http://stein.cshl.org/WWW/software/CGI/examples/
Yes, we could use the wiki for this. There are quite a few "crawling" examples in the Nevow's examples/ directory too. Perhaps the wiki page should list the examples/ as a start and then others can add to it over time with contrib resources etc. I probably have simple examples sitting on disk here. I will commit anything I can find to sandbox/mg/ and then perhaps we can move some into examples/ if they are useful. You might want to track the subversion repository, even if it's just for examples.
Aside from being great for beginners, there is another great benefit to lots of small and medium examples. A framework built for one application tends can be a bit myopic. If there are lots of little examples, each showing how to do one element cleanly and clearly, the framework will probably need to bend a little (or a lot!) and everyone will benefit.
Agreed, Quotient (for instance) is far too big to learn from unless there's a particular concept you need and know what to search for. Bigger applications also tend to be heavily refactored which often makes things harder to follow.
I'm still a beginner with Twisted/Nevow and, if I can figure it out, I'd love to contribute some examples. In the meantime I want to flag it as something that would be cool and worth the effort.
Great! As Donovan mentioned, there's often a few people on the #twisted.web IRC channel to help you get going. If you can come up with useful examples then I'm confident someone will add them to the SVN repository. Cheers, Matt -- __ / \__ Matt Goodall, Pollenation Internet Ltd \__/ \ w: http://www.pollenation.net __/ \__/ e: matt@pollenation.net / \__/ \ t: +44 (0)113 2252500 \__/ \__/ / \ Any views expressed are my own and do not necessarily \__/ reflect the views of my employer.
participants (5)
-
Alex Levy
-
Donovan Preston
-
Ellers
-
Jonathan Vanasco
-
Matt Goodall