Page object design: wrapping a dictionary containing data
I've got a Page object that derives all its data from a dictionary, eg: { 'project_name': 'project', 'project_description': 'hello', # ... you get the idea } What's a good way for the Page object to wrap that dictionary that doesn't involve doing this: def data_name(self, ctx, data): return self.d['project_name'] def data_description(self, ctx, data): return self.d['project_description'] # and so on for every key in the dictionary I vaguely recall that the equivalent of this used to be possible in Woven: def data_project(self, ctx, data): return self.d and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this? -Mary
Mary Gardiner wrote:
What's a good way for the Page object to wrap that dictionary that doesn't involve doing this:
def data_name(self, ctx, data): return self.d['project_name']
...
I vaguely recall that the equivalent of this used to be possible in Woven:
def data_project(self, ctx, data): return self.d
and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this?
heya Mary, there's a lot of Nevow magic I don't know, but in case something doesn't exist, something like the following should work, albeit, pretty crude: python -c ' class C: def __getattr__( self, attr ): if attr.startswith( "data_" ): return lambda ctx, data, s=self, a=attr : s.d["project_%s" % a[len("data_"):]] raise AttributeError c = C() c.d = { "project_name" : "roar" } ctx = "ned" data = "fred" print c.data_name( ctx, data ) ' Andy.
On Sun, 2005-01-23 at 20:14 +1000, Andy Gayton wrote:
Mary Gardiner wrote:
What's a good way for the Page object to wrap that dictionary that doesn't involve doing this:
def data_name(self, ctx, data): return self.d['project_name']
...
I vaguely recall that the equivalent of this used to be possible in Woven:
def data_project(self, ctx, data): return self.d
and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this?
heya Mary,
there's a lot of Nevow magic I don't know, but in case something doesn't exist, something like the following should work, albeit, pretty crude:
python -c ' class C: def __getattr__( self, attr ): if attr.startswith( "data_" ): return lambda ctx, data, s=self, a=attr : s.d["project_%s" % a[len("data_"):]] raise AttributeError
c = C()
c.d = { "project_name" : "roar" } ctx = "ned" data = "fred"
print c.data_name( ctx, data )
I'm not entirely sure where the above would be used but it *looks* suspiciously like some sort of pseudo-adaption for type C. If that's the case then you can register an inevow.IContainer adapter and avoid polluting your application classes with stuff that only Nevow needs ... class Person: def __init__(self, name, address): self.name = name self.address = address class PersonContainer(Adapter): __implements__ = inevow.IContainer, def child(self, name): return getattr(self.original, name) registerAdapter(PersonContainer, Person, inevow.IContainer) Yes, I agree it's a bit long-winded to have to do that every time ;-). So, there is now a ready made adapter for this in svn trunk - accessors.ObjectContainer - that does the above. Just register it for your type and it will magically work ... class Person: def __init__(self, name, address): self.name = name self.address = address registerAdapter(accessors.ObjectContainer, Person, inevow.IContainer) There's an example of this in svn trunk too. See, objcontainer.py. Hope this helps. Cheers, Matt
Hope this helps.
Yeah it all does, thanks Matt. Still struggling with the trade off between spending a couple of hours to find a nevow provided way of doing things vs an off the top of the head hack using traditional python magic ... as should be expected when using a .3 release framework :) Threads like this help a lot. cheers, Andy.
Mary Gardiner <mary-twisted@puzzling.org> writes:
I've got a Page object that derives all its data from a dictionary, eg:
{ 'project_name': 'project', 'project_description': 'hello', # ... you get the idea }
What's a good way for the Page object to wrap that dictionary that doesn't involve doing this:
def data_name(self, ctx, data): return self.d['project_name']
def data_description(self, ctx, data): return self.d['project_description']
# and so on for every key in the dictionary
I vaguely recall that the equivalent of this used to be possible in Woven:
def data_project(self, ctx, data): return self.d
and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this?
I think something like this: def data_dict(self, thing): return self.d[thing] then nevow:data="dict project_name" shoud work. I think. Cheers, mwh -- 39. Re graphics: A picture is worth 10K words - but only those to describe the picture. Hardly any sets of 10K words can be adequately described with pictures. -- Alan Perlis, http://www.cs.yale.edu/homes/perlis-alan/quotes.html
On Sun, 2005-01-23 at 10:24 +0000, Michael Hudson wrote:
Mary Gardiner <mary-twisted@puzzling.org> writes:
I've got a Page object that derives all its data from a dictionary, eg:
{ 'project_name': 'project', 'project_description': 'hello', # ... you get the idea }
What's a good way for the Page object to wrap that dictionary that doesn't involve doing this:
def data_name(self, ctx, data): return self.d['project_name']
def data_description(self, ctx, data): return self.d['project_description']
# and so on for every key in the dictionary
I vaguely recall that the equivalent of this used to be possible in Woven:
def data_project(self, ctx, data): return self.d
and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this?
I think something like this:
def data_dict(self, thing): return self.d[thing]
then nevow:data="dict project_name" shoud work. I think.
This is a parameterised data_ method, right? In which case it should look like: def data_dict(self, thing): def _(ctx, data): return self.d[thing] return _ Parameterised render_ methods look similar. Basically, Nevow expects parameterised data_ and render_ methods to return a callable (the _ function in the above example) with a signature of (ctx, data). The "weird" syntax is due to some crazy magic in the stan flatteners. There's not a lot we can do about that right now, although I think it may be possible to fix in the future. Having said all that, there may be better ways of doing this anyway, i.e. provide an inevow.IContainer adapter or use the standard adapters Nevow provides for tuple, list and dict. See my other posts for more. Cheers, Matt
On Jan 23, 2005, at 2:24 AM, Michael Hudson wrote:
Mary Gardiner <mary-twisted@puzzling.org> writes:
I've got a Page object that derives all its data from a dictionary, eg:
{ 'project_name': 'project', 'project_description': 'hello', # ... you get the idea }
What's a good way for the Page object to wrap that dictionary that doesn't involve doing this:
def data_name(self, ctx, data): return self.d['project_name']
def data_description(self, ctx, data): return self.d['project_description']
# and so on for every key in the dictionary
I vaguely recall that the equivalent of this used to be possible in Woven:
def data_project(self, ctx, data): return self.d
and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this?
Model path notation (/ and ..) are not yet supported by Nevow. But you don't need model path notation to do what you want. If all you want to do is pass a dict to the Page and have template directives locate data in that dict, you don't have to do anything at all: rend.Page( dict(one=1, two=2), docFactory=loaders.xmlstr( """<html xmlns:n="http://nevow.com/ns/nevow/0.1"> <div n:render="string" n:data="one" /> <span n:render="string" n:data="two" /> </html>""")).renderSynchronously() <html><div>1</div><span>2</span></html> Is it really that hard to figure out that things like this are possible? :-( dp
On Mon, Jan 24, 2005, Donovan Preston wrote:
Is it really that hard to figure out that things like this are possible? :-(
I should critique the existing docs for you, but I tend to skim a lot, and it's possible the data is there. It's quite difficult to work it out by reading the nevow source itself though. I spent around an hour on it, and Andrew spent two. -Mary
On Mon, 24 Jan 2005 07:22:00 -0800, Donovan Preston <dp@ulaluma.com> wrote:
rend.Page( dict(one=1, two=2), docFactory=loaders.xmlstr( """<html xmlns:n="http://nevow.com/ns/nevow/0.1"> <div n:render="string" n:data="one" /> <span n:render="string" n:data="two" /> </html>""")).renderSynchronously()
<html><div>1</div><span>2</span></html>
I might be misunderstanding something... but what's the point of having http://nevow.com/ns/nevow/0.[123] for the xmlns declaration if that URL just 404s?
On Mon, Jan 24, 2005 at 14:39:00 -0700, Jason Mobarak wrote:
I might be misunderstanding something... but what's the point of having http://nevow.com/ns/nevow/0.[123] for the xmlns declaration if that URL just 404s?
It just needs to be a unique name, it doesn't specifically have to point to anything (although often the URL points to a DTD or similar). -- mithrandi, i Ainil en-Balandor, a faer Ambar
On Mon, Jan 24, 2005, Donovan Preston wrote:
Model path notation (/ and ..) are not yet supported by Nevow. But you don't need model path notation to do what you want. If all you want to do is pass a dict to the Page and have template directives locate data in that dict, you don't have to do anything at all:
I do, as it happens, want to do some rendering using the data in the dictionary too... :( -Mary
On Sun, 2005-01-23 at 20:12 +1100, Mary Gardiner wrote:
I've got a Page object that derives all its data from a dictionary, eg:
{ 'project_name': 'project', 'project_description': 'hello', # ... you get the idea }
What's a good way for the Page object to wrap that dictionary that doesn't involve doing this:
def data_name(self, ctx, data): return self.d['project_name']
def data_description(self, ctx, data): return self.d['project_description']
# and so on for every key in the dictionary
I vaguely recall that the equivalent of this used to be possible in Woven:
def data_project(self, ctx, data): return self.d
and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this?
If a dict is the currently in scope data (the IData) for a template then nested data directives will look inside the dict (see accessors.DictionaryContainer for details): <div n:data="personAsDict"> <p n:data="name">...</p> <p n:data="address">...</p> </div> In that example, the 'name' and 'address' directives are equivalent to personAsDict['name'] and personAsDict['address'] respectively. There's also the mapping render (rend.mapping) That fills slots with the content of the dict: <div n:data="personAsDict" n:render="mapping"> <p><n:slot name="name" /></p> <p><n:slot name="address" /></p> </div> Hope this helps. Cheers, Matt
On Sun, 2005-01-23 at 10:27 +0000, Matt Goodall wrote:
On Sun, 2005-01-23 at 20:12 +1100, Mary Gardiner wrote:
I've got a Page object that derives all its data from a dictionary, eg:
{ 'project_name': 'project', 'project_description': 'hello', # ... you get the idea }
What's a good way for the Page object to wrap that dictionary that doesn't involve doing this:
def data_name(self, ctx, data): return self.d['project_name']
def data_description(self, ctx, data): return self.d['project_description']
# and so on for every key in the dictionary
I vaguely recall that the equivalent of this used to be possible in Woven:
def data_project(self, ctx, data): return self.d
and then that the data items were accessible by (say) stan.directive("project/project_name"). This doesn't look like its supported in Nevow. Is this correct? What alternative designs are there for something like this?
If a dict is the currently in scope data (the IData) for a template then nested data directives will look inside the dict (see accessors.DictionaryContainer for details):
<div n:data="personAsDict"> <p n:data="name">...</p> <p n:data="address">...</p> </div>
The stan equivalent being, tags.p(data=tags.directive('name')).
In that example, the 'name' and 'address' directives are equivalent to personAsDict['name'] and personAsDict['address'] respectively.
There's also the mapping render (rend.mapping) That fills slots with the content of the dict:
<div n:data="personAsDict" n:render="mapping"> <p><n:slot name="name" /></p> <p><n:slot name="address" /></p> </div>
Hope this helps.
Cheers, Matt
_______________________________________________ Twisted-web mailing list Twisted-web@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web
participants (7)
-
Andy Gayton
-
Donovan Preston
-
Jason Mobarak
-
Mary Gardiner
-
Matt Goodall
-
Michael Hudson
-
Tristan Seligmann