Ok, so currently if you want dynamic stuff to happen in an attribute you have to do something along the lines of this. <a render="mylink"> <nevow:attr name="href"> <nevow:slot name="link" /> </nevow:attr> <nevow:slot name="label" /> </a> def render_mylink(self, ctx, data): ctx.fillSlots('link', data[0]) ctx.fillSlots('label', data[1]) return ctx.tag Which is horrendously ugly and difficult to explain to pretty much anyone. Now, there are plenty of other solutions to this problem, but none of them provide the flexability for the template author as <nevow:attr> and <nevow:slot> do. For instance: <nevow:attr name="href"> /users/<nevow:slot name="username" />/images </ nevow:attr> Works perfectly well. Which according to fzZzy is the main reason for choosing this syntax. A comparison to this with the syntax of TAL was recently mentioned on the ML (Comparison with ZPT [Was: [Twisted-web] Sub-tag level templating in Nevow: possible?]), and the TAL syntax seems to be cleaner, though I'm not sure if it provides the above functionality. While discussing it on IRC I came to a conclusion that the following would be comfortable, and flexible syntax alternative (not replacement) for <nevow:attr> <a href="/images/archives/%(year)/%(month)/%(day)" nevow:attributes="href=year,month,day alt=label"> <nevow:slot name="label" /> </a> basically when the template was getting parsed, the Tag instance would end up something like this. Tag(name='a', attributes={'href': ['/images/archives/', slot(name='year'), slot(name='month'), slot(name='day')] }) It provides the flexibility, and in my opinion is just a little more intuitive than <nevow:attr>. --David
On Tue, Oct 19, 2004 at 12:42:46AM -0700, David Reid wrote: [...]
Which is horrendously ugly and difficult to explain to pretty much anyone. Now, there are plenty of other solutions to this problem, but none of them provide the flexability for the template author as <nevow:attr> and <nevow:slot> do.
For instance: <nevow:attr name="href"> /users/<nevow:slot name="username" />/images </ nevow:attr>
Works perfectly well. Which according to fzZzy is the main reason for choosing this syntax.
A comparison to this with the syntax of TAL was recently mentioned on the ML (Comparison with ZPT [Was: [Twisted-web] Sub-tag level templating in Nevow: possible?]), and the TAL syntax seems to be cleaner, though I'm not sure if it provides the above functionality. While discussing
TAL does allow this, in two ways (that I know of): First, there's the hackish way: <a tal:attributes="href python:'/users/' + context/username + '/images'" /> The second way is to put this sort of complex code a view: class ViewBlah: def __init__(self, context, request): self.context = context self.request = request def imagesPath(self): return '/users/' + self.context.username + '/images' then you can do: <a tal:attributes="href view/imagesPath" /> -Andrew.
On Tue, 2004-10-19 at 02:51, Andrew Bennetts wrote:
TAL does allow this, in two ways (that I know of):
First, there's the hackish way:
They're both hackish ways in my opinion, and the latter Another alternative is for the alternative syntax to not even support such behavior, and only be for the general case which would look something like this: <a nevow:attributes="href=link alt=label"><nevow:slot name="label" /></a> (Looks an aweful lot like mg's attr.tac example, doesn't it?)
On Tue, Oct 19, 2004 at 12:10:37PM -0700, David Reid wrote:
On Tue, 2004-10-19 at 02:51, Andrew Bennetts wrote:
TAL does allow this, in two ways (that I know of):
First, there's the hackish way:
They're both hackish ways in my opinion, and the latter Another alternative is for the alternative syntax to not even support such behavior, and only be for the general case which would look something like this:
<a nevow:attributes="href=link alt=label"><nevow:slot name="label" /></a>
(Looks an aweful lot like mg's attr.tac example, doesn't it?)
Firstly, I really don't know Nevow, I just lurk on the discussions about it. I mention ZPT from time-to-time mainly out of selfishness: it would be easier for me to learn Nevow if it were more like ZPT ;) Now, on to the reply... mg's attr.tac has this in the template: <ul nevow:data="links" nevow:render="sequence"> <li nevow:pattern="item" nevow:render="link"><a href="#" nevow:render="attribute href=link,alt=label"><nevow:slot name="label">label</nevow:slot></a></li> </ul> I don't see what this does that is different to: <ul tal:repeat="linkinfo context/links"> <li><a href="#" tal:attributes="href linkinfo/link; label linkinfo/label"/></li> </ul> Although I don't totally understand why mg's attr.tac has a nevow:slot tag for label and not link, as far as I can tell the ZPT I give here is equivalent in concept. Explanations and/or corrections welcome! Of course, my ZPT examples requires that the code would require there to be a linkinfo class, e.g. class LinkInfo: def __init__(self, link, label): self.link = link self.label = label And context/links would just be a list of these. I don't see this as being any more complex than what attr.tac does, though. If nothing else, I hope this discussion can serve as the basis for a "Nevow for ZPT users" tutorial. -Andrew.
On Tue, 2004-10-19 at 23:06 +0200, Andrew Bennetts wrote:
On Tue, Oct 19, 2004 at 12:10:37PM -0700, David Reid wrote:
On Tue, 2004-10-19 at 02:51, Andrew Bennetts wrote:
TAL does allow this, in two ways (that I know of):
First, there's the hackish way:
They're both hackish ways in my opinion, and the latter Another alternative is for the alternative syntax to not even support such behavior, and only be for the general case which would look something like this:
<a nevow:attributes="href=link alt=label"><nevow:slot name="label" /></a>
(Looks an aweful lot like mg's attr.tac example, doesn't it?) [...] mg's attr.tac has this in the template:
<ul nevow:data="links" nevow:render="sequence"> <li nevow:pattern="item" nevow:render="link"><a href="#" nevow:render="attribute href=link,alt=label"><nevow:slot name="label">label</nevow:slot></a></li> </ul>
I don't see what this does that is different to:
I think that was David's point, they're basically doing the same thing with a different syntax.
<ul tal:repeat="linkinfo context/links"> <li><a href="#" tal:attributes="href linkinfo/link; label linkinfo/label"/></li> </ul>
Although I don't totally understand why mg's attr.tac has a nevow:slot tag for label and not link, as far as I can tell the ZPT I give here is equivalent in concept. Explanations and/or corrections welcome!
The attribute renderer in attr.tac example updates updates from values in slots, i.e. href is set to the href slot and alt (yeah, it should be label;-)) is set to the label slot. The slot *inside* the <a>...</a> is actually nothing to do with the attribute renderer but ensures that the label also appears inside the element. I don't know ZPT well enough to know if your example does exactly the same (I can't see how it could) but that really doesn't matter for this discussion anyway. I should point out that most of the time, I use the <n:attr ...
<n:slot ...></n:attr> syntax because it's always there and it's more flexible. I wrote the attr.tac more as an example of how one might implement something like this using a renderer although it does have the benefit of being compact for really simple stuff.
Of course, my ZPT examples requires that the code would require there to be a linkinfo class, e.g.
class LinkInfo: def __init__(self, link, label): self.link = link self.label = label
And context/links would just be a list of these. I don't see this as being any more complex than what attr.tac does, though.
This is probably the right way with Nevow too. The difference with Nevow is that Nevow refuses to look inside objects it doesn't understand by default so it would never use getattr unless explicitly told to. You can tell Nevow how to look inside objects by registering a inevow.IContainer adapter. We've talked about providing a IContainer adapter that does getattr magic in Nevow but it would be up to the developer to register the adapter for specific types.
If nothing else, I hope this discussion can serve as the basis for a "Nevow for ZPT users" tutorial.
I guess I should learn ZPT properly sometime, just to get another angle on all this. 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.
On Wed, Oct 20, 2004 at 10:26:36AM +0100, Matt Goodall wrote:
On Tue, 2004-10-19 at 23:06 +0200, Andrew Bennetts wrote: [...]
<ul tal:repeat="linkinfo context/links"> <li><a href="#" tal:attributes="href linkinfo/link; label linkinfo/label"/></li> </ul>
Although I don't totally understand why mg's attr.tac has a nevow:slot tag for label and not link, as far as I can tell the ZPT I give here is equivalent in concept. Explanations and/or corrections welcome!
The attribute renderer in attr.tac example updates updates from values in slots, i.e. href is set to the href slot and alt (yeah, it should be label;-)) is set to the label slot. The slot *inside* the <a>...</a> is actually nothing to do with the attribute renderer but ensures that the label also appears inside the element.
Oh, right. I get it now, duh :)
I don't know ZPT well enough to know if your example does exactly the same (I can't see how it could) but that really doesn't matter for this discussion anyway.
My ZPT to be equivalent should be: <ul tal:repeat="linkinfo context/links"> <li><a href="#" tal:attributes="href linkinfo/link; alt linkinfo/label" tal:content="linkinfo/label"/>Label will go here</li> </ul> I think it's a shame that no-one seems to know both ZPT and Nevow, as I suspect there may be something they can learn from each other, as they have some similar goals. I'd like to learn Nevow (although I'm really no ZPT expert), but time is always the problem...
I should point out that most of the time, I use the <n:attr ...
<n:slot ...></n:attr> syntax because it's always there and it's more flexible. I wrote the attr.tac more as an example of how one might implement something like this using a renderer although it does have the benefit of being compact for really simple stuff.
Of course, my ZPT examples requires that the code would require there to be a linkinfo class, e.g.
class LinkInfo: def __init__(self, link, label): self.link = link self.label = label
And context/links would just be a list of these. I don't see this as being any more complex than what attr.tac does, though.
This is probably the right way with Nevow too. The difference with Nevow is that Nevow refuses to look inside objects it doesn't understand by default so it would never use getattr unless explicitly told to.
I don't know exactly where this happens in Zope 3, but it won't by default either. So, the code would look more like this: from zope.interface import Interface, Attribute, implements class ILinkInfo(Interface): link = Attribute('URI that a link points to') label = Attribute('Short description of the link') class LinkInfo: implements(ILinkInfo) ... And then usually in a ZCML file say that ZPT (or really the publisher in general) is allowed to access attributes and methods defined in ILinkInfo.
You can tell Nevow how to look inside objects by registering a inevow.IContainer adapter. We've talked about providing a IContainer adapter that does getattr magic in Nevow but it would be up to the developer to register the adapter for specific types.
I see. This seems essentially equivalent to the ZPT way -- registering an adapter from ILinkInfo to IContainer. Zope does things via security declarations because there's a desire to allow relatively untrusted sources to write page templates, I guess. There's more in common here than different, though :)
If nothing else, I hope this discussion can serve as the basis for a "Nevow for ZPT users" tutorial.
I guess I should learn ZPT properly sometime, just to get another angle on all this.
And I should learn Nevow :) -Andrew.
On Wed, 20 Oct 2004 14:01:36 +0200, Andrew Bennetts <andrew-twisted@puzzling.org> wrote:
I think it's a shame that no-one seems to know both ZPT and Nevow, as I suspect there may be something they can learn from each other, as they have some similar goals. I'd like to learn Nevow (although I'm really no ZPT expert), but time is always the problem...
Well, I just did my first in-depth zope2/plone project (heavily involving ZPT) in the last couple of weeks, and I'm also versed in Nevow's templates. However, I haven't yet had a need to do computed attributes in a situation where it would be problematic to just set them in a render_ method for the entire tag. I'll pipe up if I ever do. -- Twisted | Christopher Armstrong: International Man of Twistery Radix | Release Manager, Twisted Project ---------+ http://radix.twistedmatrix.com
On Oct 19, 2004, at 2:51 AM, Andrew Bennetts wrote:
TAL does allow this, in two ways (that I know of):
First, there's the hackish way:
<a tal:attributes="href python:'/users/' + context/username + '/images'" />
The second way is to put this sort of complex code a view:
class ViewBlah: def __init__(self, context, request): self.context = context self.request = request def imagesPath(self): return '/users/' + self.context.username + '/images'
then you can do:
<a tal:attributes="href view/imagesPath" />
Which is exactly what Nevow allows you to do very easily, as well. Currently, if you want to put this type of information in python code, you can use a technique similar to your second example: def render_imagesPath(self, ctx, username): return ctx.tag(href=['/users/', username, '/images']) If you'd rather put that information in the template, you can do it using nevow:attr: <a><nevow:attr name="href">/users/<nevow:slot name="username" />/images</nevow:attr></a> Again, the reason I arrived at this syntax is because it doesn't require you to learn any new substitution syntax and the full range of nevow functionality is available. It's consistent. I don't see what the huge advantage of dreid's proposed nevow:attributes syntax is, in fact I'm not even sure how it would work. I'm against it mostly because it's another mechanism users have to learn, and is only useful for one small use case. Another possibility is a python renderer: <a nevow:render="python ctx.tag(href=["/users/", slot('username'), "/images"])" /> The implementation would be pretty simple: def render_python(self, ctx, code): def evalIt(ctx, data): return eval(code, {'ctx': ctx, 'data': data}) return evalIt dp
At 2004-10-19 12:42 AM -0700, you wrote:
Ok, so currently if you want dynamic stuff to happen in an attribute you have to do something along the lines of this.
<a render="mylink"> <nevow:attr name="href"> <nevow:slot name="link" /> </nevow:attr> <nevow:slot name="label" /> </a>
def render_mylink(self, ctx, data): ctx.fillSlots('link', data[0]) ctx.fillSlots('label', data[1])
return ctx.tag
Which is horrendously ugly and difficult to explain to pretty much anyone. Now, there are plenty of other solutions to this problem, but none of them provide the flexability for the template author as <nevow:attr> and <nevow:slot> do.
I haven't started using nevow:attr yet. I've done some straightforward string substitutions. Anathema to the Twisted Way, I suspect, but it works. An example from a working application: [In TEMPLATE] <a href='/daily/%s' nevow:data='today' nevow:render='interpolateHref'>Today</a> [In Renderer] def render_interpolateHref(self, context, data): """ Interpolate data into href attribute of tag. Href attribute is assumed to contain a '%s' formatting spec. """ tag = context.tag() href = tag.attributes['href'] tag.attributes['href'] = href % str(data) return tag FWIW. - Sam __________________________________________________________ Spinward Stars, LLC Samuel Reynolds Software Consulting and Development 303-805-1446 http://SpinwardStars.com/ sam@SpinwardStars.com
participants (6)
-
Andrew Bennetts
-
Christopher Armstrong
-
David Reid
-
Donovan Preston
-
Matt Goodall
-
Samuel Reynolds