Objects with multiple parents and storage flexibility, ZPatterns?
Hi, Once again I'm back at trying to solve this problem, hopefully with a little more knowledge this time ;-) What I'd like: 'Zope' objects of type 'X', which can have multiple parents and can contain other objects of type 'X', where storage isn't necessarily tied to the ZODB but where the objects have a normal properties page (in terms of use, again, it'd be nice if it could be stored anywhere) and participate in all the normal Zope security and management interface processes, and they need to be catalogable. This sounds like ZPatterns to me, am I right? If so, it appears there are two choices: 1. Folder w/Customiser Support (FwCS ;-) and DataSkins 2. Specialist with one or more Racks and DataSkins Which one of these would be most appropriate? FwCS containg DataSkins that also mix in the Folder class sound like they'd give a closer approximation to 'real Zope objects', but Racks sound like the only way that objects of the same metatype can come from different sources (eg, some objects of type 'X' from ZODB, some from SQL, some from LDAP ,etc) and seem to be more flexible in general, but can I have DataSkins that nest stored in a specialists' rack, eg: http://server:8080/specialist/dataskin1/dataskin2 How about doing something like: http://server:8080/specialist/dataskin1/dataskin2/manage ? Any help is good help, sorry this is a bit rambling, if you need mroe info, I'll be happy to supply it :-S cheers, Chris
Hi Chris, Random thoughts follow. ;-) I think that if you make your DataSkins folderish it will be hard to make the storage anything other than ZODB. However, Steve Alexander posted a neat trick the other day where __bobo_traverse__ is supplied by an attribute provider. You could use this to make your DataSkins traversable. Let's say your objects have an attribute that defines them in the context of their parent (e.g., dataskin2 in your example URL), let's call it 'context_id'. You may have six objects with the same context_id, but they would all have different parents. Now.. you could implement a search interface that finds an object in context. GetObjectInContextOfParent( context_id, parent_id ) Each object must also (of course) have a parent_id, unless it's a root level object. In SQL this might be: select * from objectXs where parent_id = 'dataskin1_id' and context_id = 'dataskin2' or it could be a catlog search, if you're in ZODB. Now for the traversal interface: def __bobo_traverse__(self, REQUEST, name): ob = getattr(self, name, _marker) if ob is _marker: ob = self.GetObjectInContextOfParent( context_id = name, parent_id = self.id) if ob is not None: return ob raise 'NotFound' return ob Totally untested of course. ;-) Anyway the idea would be to *not* use folderish DataSkins, but to build a hierarchy out of them that could be traversed. -steve
Thanks... this sounds a lot like what I'm after :-) Steve Spicklemire wrote:
I think that if you make your DataSkins folderish it will be hard to make the storage anything other than ZODB.
Well, I don't mind the 'skins' being stored in the ZODB, but, as Steve A mentioned, I _would_ like stuff created in the RDBMS to 'magically appear' in the Zope side of things. I guess that means FwCS and folder-subclassing DataSkins are a no-no?
Let's say your objects have an attribute that defines them in the context of their parent (e.g., dataskin2 in your example URL),
their id in Zope parlance, right?
let's call it 'context_id'. You may have six objects with the same context_id, but they would all have different parents.
They may each have mutliple parents too ;-) The point for me is that the id (context_id in your example) is unique in terms of _only_ the following constraint: No parent may have more than one child with the same id. This is actually how the ZODB works except that it objects in the ZODB may only have one parent (well, at least ZODBs managed with Zope ;-)
Now.. you could implement a search interface that finds an object in context.
GetObjectInContextOfParent( context_id, parent_id )
might be better if it resolved a path into an object, like Zope does, hence my keenness to see if there isn't a simple way I can make Zope and Zpatterns do the bulk of the work, just with the tweaks I need...
Now for the traversal interface:
def __bobo_traverse__(self, REQUEST, name): ob = getattr(self, name, _marker) if ob is _marker: ob = self.GetObjectInContextOfParent( context_id = name, parent_id = self.id) if ob is not None: return ob raise 'NotFound' return ob
looks good...
Totally untested of course. ;-) Anyway the idea would be to *not* use folderish DataSkins, but to build a hierarchy out of them that could be traversed.
Hurm... I'd love them to have a UI identical to normal Zope folders/objectmanagers, though, with properties, a security tab, and, in a dream world, the ability to drop normal DTML methods, python Scripts and the like into the foldersish objects. Is this asking for too much? ;-) Chris
Hi Chris,
"Chris" == Chris Withers <chrisw@nipltd.com> writes:
Chris> Steve Spicklemire wrote: >> I think that if you make your DataSkins folderish it will be >> hard to make the storage anything other than ZODB. Chris> Well, I don't mind the 'skins' being stored in the ZODB, Chris> but, as Steve A mentioned, I _would_ like stuff created in Chris> the RDBMS to 'magically appear' in the Zope side of Chris> things. I guess that means FwCS and folder-subclassing Chris> DataSkins are a no-no? No... I don't think so! If you don't mind keeping stuff in ZODB then you *could* have a traversal interface that made stuff 'appear' wherever you want it to, though its persistent storage would 'really' be in a Rack or FwCS. >> Let's say your objects have an attribute that defines them in >> the context of their parent (e.g., dataskin2 in your example >> URL), Chris> their id in Zope parlance, right? Hmm. not really... the Zope 'id' is used by the Rack to keep track of all the objects of a single type. If all your 'X's are kept in one Rack, they all need a unique 'id'. The idea context_id is an id-like attribute that 'plays the role of id' in the context of a particular parent. It's probably a bad name... but all I could think of in 5 minutes... >> let's call it 'context_id'. You may have six objects with the >> same context_id, but they would all have different parents. Chris> They may each have mutliple parents too ;-) The point for Chris> me is that the id (context_id in your example) is unique in Chris> terms of _only_ the following constraint: No parent may Chris> have more than one child with the same id. This is Chris> actually how the ZODB works except that it objects in the Chris> ZODB may only have one parent (well, at least ZODBs managed Chris> with Zope ;-) Wow... multiple parents, multiple children.. it's almost incestuous! So long as you can write queries for 'find parents for child x' and 'find children for parent y' it shouldn't matter. If not you'll need to keep references to parents/childred stored in the objects and that can be bothersome, but possible. >> Now.. you could implement a search interface that finds an >> object in context. >> >> GetObjectInContextOfParent( context_id, parent_id ) Chris> might be better if it resolved a path into an object, like Chris> Zope does, hence my keenness to see if there isn't a simple Chris> way I can make Zope and Zpatterns do the bulk of the work, Chris> just with the tweaks I need... I'm not sure how the path will help you at this point... but if you need it you can always ask Zope for it once traversal is complete. >> Now for the traversal interface: >> >> def __bobo_traverse__(self, REQUEST, name): ob = getattr(self, >> name, _marker) if ob is _marker: ob = >> self.GetObjectInContextOfParent( context_id = name, parent_id = >> self.id) if ob is not None: return ob raise 'NotFound' return >> ob Chris> looks good... >> Totally untested of course. ;-) Anyway the idea would be to >> *not* use folderish DataSkins, but to build a hierarchy out of >> them that could be traversed. Chris> Hurm... I'd love them to have a UI identical to normal Zope Chris> folders/objectmanagers, though, with properties, a security Chris> tab, and, in a dream world, the ability to drop normal DTML Chris> methods, python Scripts and the like into the foldersish Chris> objects. Chris> Is this asking for too much? ;-) You can never *ask* for too much. ;-) Seriously though... for this you'll probably need to store the objects persistently in the Rack(s), though you could farm some of their attributes out to other data storage systems with SkinScript. Nothing will prevent you from making your DataSkins inherit from ObjectManager or Folder, but you won't be able to completely 'virtualize' them. The only way I *think* you could make this work with completely virtual data-skins is to create 'sister' classes to everything you wanted to add (e.g. 'SkinDTML Method' and 'SkinPython Script' which would be new classes that inherit from DataSkin *and* the class you want to emulate (and probably yet another class that hanldles the interconnection glue parents/context and all that). Then you'd need to add whatever attribute providers were necessary to keep all the attributes of the original classes (e.g., DTML Method) in your external storage. But it sounds like you just want to keep 'some' of the associated data in the external source... so I don't think any of that will be necessary. good luck! -steve Chris> Chris
Steve Spicklemire wrote:
No... I don't think so! If you don't mind keeping stuff in ZODB then you *could* have a traversal interface that made stuff 'appear' wherever you want it to, though its persistent storage would 'really' be in a Rack or FwCS.
Cool... how would I go about doing that?
Hmm. not really... the Zope 'id' is used by the Rack to keep track of all the objects of a single type. If all your 'X's are kept in one Rack, they all need a unique 'id'.
Ah, yes, now I see, in my case, as with the ZODB, the unique id would be the path from the specialist/FwCS to the DataSkin in question, ending in the dataskin's ID, I think :-S The difference is that, because of the multiple parents thing, unique id -> dataskin isn't a one to one mapping. many unique id's map onto one dataskin. I suppose that means the _actual_ unique id for the dataskin needs to be a unique integer number or some such. But I guess the user would never need to be exposed to that? Does strike me that this is all redo-ing Zope's traversal stuff, which is why I'm trying to find a better way... wagh! My head hurts :-S
The idea context_id is an id-like attribute that 'plays the role of id' in the context of a particular parent. It's probably a bad name... but all I could think of in 5 minutes...
I think id would be better, because it's closest to Zope's notion of id, the bit that goesi nto the Rack probably wants to be called 'unique idenitifier' or maybe even 'path' depending on what gets used :-S
Wow... multiple parents, multiple children.. it's almost incestuous!
inbred objects, now there's a concept ;-)
So long as you can write queries for 'find parents for child x' and 'find children for parent y' it shouldn't matter.
cool...
Chris> Hurm... I'd love them to have a UI identical to normal Zope Chris> folders/objectmanagers, though, with properties, a security Chris> tab, and, in a dream world, the ability to drop normal DTML Chris> methods, python Scripts and the like into the foldersish Chris> objects.
Chris> Is this asking for too much? ;-)
You can never *ask* for too much. ;-)
But then what happens if I ask how to do it?
Seriously though... for this you'll probably need to store the objects persistently in the Rack(s),
Why?
though you could farm some of their attributes out to other data storage systems with SkinScript. Nothing will prevent you from making your DataSkins inherit from ObjectManager or Folder, but you won't be able to completely 'virtualize' them.
Well, that may not be a problem. The important thing is that if someone creates a record in a.n.other system, then one of these 'virtual' objects automatically appears in the Zope side of things... reckon that's not too hard?
The only way I *think* you could make this work with completely virtual data-skins is to create 'sister' classes to everything you wanted to add (e.g. 'SkinDTML Method' and 'SkinPython Script' which would be new classes that inherit from DataSkin *and* the class you want to emulate (and probably yet another class that hanldles the interconnection glue parents/context and all that). Then you'd need to add whatever attribute providers were necessary to keep all the attributes of the original classes (e.g., DTML Method) in your external storage. But it sounds like you just want to keep 'some' of the associated data in the external source... so I don't think any of that will be necessary.
Why would the sister classes be needed? Anyway, how do I break this down into small beginner sized steps and start doing it? thanks for all your help, Chris
Chris Withers wrote:
Hi,
Once again I'm back at trying to solve this problem, hopefully with a little more knowledge this time ;-)
What I'd like: 'Zope' objects of type 'X', which can have multiple parents and can contain other objects of type 'X', where storage isn't necessarily tied to the ZODB but where the objects have a normal properties page (in terms of use, again, it'd be nice if it could be stored anywhere) and participate in all the normal Zope security and management interface processes, and they need to be catalogable.
This sounds like ZPatterns to me, am I right?
If so, it appears there are two choices: 1. Folder w/Customiser Support (FwCS ;-) and DataSkins 2. Specialist with one or more Racks and DataSkins
Which one of these would be most appropriate?
If you use a Folder w/ Customizer Support, you'll need to create all the DataSkin instances in the ZODB, just as if they were normal ZClass (or whatever) instances. Thus, the instances all need to be "in there" to start with. You can't add data to your external database, and expect a new Dataskin instance to pop up in the ZODB. This is what is meant by "When using Folder with Customizer Support, DataSkins are anchored in the ZODB".
FwCS containg DataSkins that also mix in the Folder class sound like they'd give a closer approximation to 'real Zope objects', but Racks sound like the only way that objects of the same metatype can come from different sources (eg, some objects of type 'X' from ZODB, some from SQL, some from LDAP ,etc) and seem to be more flexible in general, but can I have DataSkins that nest stored in a specialists' rack, eg:
You can get the data for your dataskins from a variety of sources, whether you choose to use Specialists or Folder w/ Customizer Support. However, if you use Specialists, you can have the DataSkin instances appear only when requested. Thus, you can add records to your external database, and thereby have new Dataskins available from your application.
http://server:8080/specialist/dataskin1/dataskin2
How about doing something like:
You can do this by providing the __bobo_traverse__ protocol, using SkinScript in your Specialist to give objects of the type of dataskin1 an appropriate __bobo_traverse__ method. I briefly described this on zope-dev a couple of days ago. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
Steve Alexander wrote:
If you use a Folder w/ Customizer Support, you'll need to create all the DataSkin instances in the ZODB, just as if they were normal ZClass (or whatever) instances. Thus, the instances all need to be "in there" to start with.
Shame, although if I'm really brutal and XP about this, that might not matter...
You can't add data to your external database, and expect a new Dataskin instance to pop up in the ZODB. This is what is meant by "When using Folder with Customizer Support, DataSkins are anchored in the ZODB".
Is this always going to be the case or just the current implementation?
You can get the data for your dataskins from a variety of sources, whether you choose to use Specialists or Folder w/ Customizer Support.
Cool... would creating a folder objects that subclasses FwCS _and_ DataSkin be a very bad thing, or could I maybe get what I want doing that and supplying things like objectIds with an attribute provider?
However, if you use Specialists, you can have the DataSkin instances appear only when requested. Thus, you can add records to your external database, and thereby have new Dataskins available from your application.
Hurm... could this not be achvieved if, like I mentioned earlier, objectIds, and whatever else is neeeded, is supplied by something ZPatterns-ish?
I briefly described this on zope-dev a couple of days ago.
Yup, I saw :-) Many thanks for all the help, Chris
At 05:15 PM 1/3/01 +0000, Chris Withers wrote:
What I'd like: 'Zope' objects of type 'X', which can have multiple parents and can contain other objects of type 'X', where storage isn't necessarily tied to the ZODB but where the objects have a normal properties page (in terms of use, again, it'd be nice if it could be stored anywhere) and participate in all the normal Zope security and management interface processes, and they need to be catalogable.
This sounds like ZPatterns to me, am I right?
If so, it appears there are two choices: 1. Folder w/Customiser Support (FwCS ;-) and DataSkins 2. Specialist with one or more Racks and DataSkins
Which one of these would be most appropriate? FwCS containg DataSkins that also mix in the Folder class sound like they'd give a closer approximation to 'real Zope objects', but Racks sound like the only way that objects of the same metatype can come from different sources (eg, some objects of type 'X' from ZODB, some from SQL, some from LDAP ,etc) and seem to be more flexible in general, but can I have DataSkins that nest stored in a specialists' rack, eg:
http://server:8080/specialist/dataskin1/dataskin2
How about doing something like:
You can't really "nest" DataSkins inside each other in a rack, and you really don't want to, anyway. But there's nothing that says you can't create a DataSkin subclass whose __bobo_traverse__ looks up related objects. You just can't "really" store the DataSkins inside each other. Note that if your __bobo_traverse__ uses a specialist "getXforY()" call, you can "store" objects from different databases (racks) "inside" each other. :)
participants (4)
-
Chris Withers -
Phillip J. Eby -
Steve Alexander -
Steve Spicklemire