add optional "folder" argument to ZClass.createInObjectManager() ?
Hi, I propose to add an optional argument to ZClass.createInObjectManager() that specifies the ObjectManager instance in which the newly-created object will reside. Currently, the ObjectManager in which an object is to be created is found through acquisition. This breaks when sub-objects are created in the constructor of their container object. For example: I have a Purchase object containing Item objects. In method PurchaseClass_add(), I create the Purchase object using PurchaseClass.createInObjectManager(). That goes fine. Then I create its contained objects using ItemClass().createInObjectManager(). Instead of going inside of the PurchaseObject, they go in the folder that contains the PurchaseObject. No manipulation of name spaces by <dtml-with> will change this - the ObjectManager is found through acquisition, not the name space. Currently, the only way out of this is to create an external method and call _setObject() directly. You can't do it from DTML at all. I propose to add a "folder" argument to createInObjectManager() so that the folder can be specified directly. The modified method appears below, please compare it to the version in ZClass.py . I have a few questions about this: 1. Am I missing an easier or more elegant way to do this? 2. Would this circumvent security in some way? 3. Can I get this change, or something that has a similar effect, into a future version of Zope? Thanks Bruce def createInObjectManager(self, id, REQUEST, RESPONSE=None, folder=None): """ Create Z instance. If called with a RESPONSE, the RESPONSE will be redirected to the management screen of the new instance's parent Folder. Otherwise, the instance will be returned. """ i=mapply(self._zclass_, (), REQUEST) if not hasattr(i, 'id') or not i.id: i.id=id durl=None if folder is None: if hasattr(self, 'Destination'): d=self.Destination if d.im_self.__class__ is FactoryDispatcher: folder=d() if folder is None: folder=self.aq_parent if not hasattr(folder,'_setObject'): folder=folder.aq_parent folder._setObject(id, i) if RESPONSE is not None: try: durl=self.DestinationURL() except: durl=REQUEST['URL3'] RESPONSE.redirect(durl+'/manage_workspace') else: return folder._getOb(id)
Bruce Perens wrote:
I have a few questions about this:
1. Am I missing an easier or more elegant way to do this?
I haven't looked at it close enough.
2. Would this circumvent security in some way?
See 1.
3. Can I get this change, or something that has a similar effect, into a future version of Zope?
Yes, I suggest you post this up to the Interfaces Wiki at: http://www.zope.org/Members/michel/Projects/Interfaces In the wish list you will see I allready mentioned an instanciation interface that you may want to elaborate on. -Michel
oops, forgot to cc the list..... On Tue, 4 Apr 2000 18:26:53 -0700 (PDT), bruce@perens.com (Bruce Perens) wrote:
Currently, the ObjectManager in which an object is to be created is found through acquisition. This breaks when sub-objects are created in the constructor of their container object. For example: I have a Purchase object containing Item objects. In method PurchaseClass_add(), I create the Purchase object using PurchaseClass.createInObjectManager(). That goes fine. Then I create its contained objects using ItemClass().createInObjectManager(). Instead of going inside of the PurchaseObject, they go in the folder that contains the PurchaseObject.
No manipulation of name spaces by <dtml-with> will change this - the ObjectManager is found through acquisition, not the name space.
agreed
1. Am I missing an easier or more elegant way to do this?
I wouldnt call it elegent, but the least ugly way to do this (afaik) is to delay constructing the sub-objects until after the constructor is complete, and the object is installed in it's context.
From a python product this is straightforward (and I use this alot):
def manage_addZCedarApp(self,id,title,REQUEST,RESPONSE): """ """ c = MyObject(str(id),wstring(title)) self._setObject(str(id),c) c.__of__(self)._after_create() # this creates the sub-objects if REQUEST is not None: return self.manage_main(self,REQUEST) For a ZClass its a bit harder, since you need to find an appropriate acquisition wrapper for the newly created object. Something like this should do (untested) <!--#with "whatever.createInObjectManager(REQUEST['id'], REQUEST)"--> <!--#/with--> <dtml-call "getattr(this(),REQUEST['id']).after_create()">
I propose to add an optional argument to ZClass.createInObjectManager() that specifies the ObjectManager instance in which the newly-created object will reside.
That option is cleaner for this particular case, but doesn't solve the more general problem. There are many resources that zope objects get using acquisition, and most of them might be useful in a constructor. Toby Dickenson tdickenson@geminidataloggers.com
participants (3)
-
bruce@perens.com -
Michel Pelletier -
Toby Dickenson