[Zope-CMF] how to store a reference?

seb bacon seb@jamkit.com
Thu, 24 Oct 2002 10:29:31 +0100


Mark McEahern wrote:
> This whole thing seems like something that I shouldn't have to jump through
> a lot of hoops to do.  

Right, you are discovering why people talk about that abstract zope 
entity called 'zen'.

So, you have a PressRelease.  It appears that you want to add Contacts 
into the same folder, and then be able to select one of these contacts 
as a property of the PressRelease edit form.

1. In the form, you want to name the select element "contacts:list". 
This will marshall the values selected by the user into a list 
automatically in their REQUEST.

http://www.zope.org/Members/Zen/howto/FormVariableTypes

2.  You *should* store the ids as a list of ids (strings) rather than as 
a list of objects.

When using ObjectManagers (folderish things like Portal Folders, etc), 
the subobjects are basically already stored as attributes of the object. 
  You what it so that some of them are 'selected'.  If you just store 
another copy of just the selected Contacts, you'll get into all sorts of 
trouble (what if someone changes one of the contacts?).

So, if you want to do it roughly in the way you have outlined, you 
*should* store the selected contacts as a list of ids, and get the 
object by id when it's requested - perhaps give the PressRelease a 
getContactById() accessor method.

Note that you can hook into a rename / move operation of something's 
subobjects by adding 'manage_beforeDelete' and / or 'manage_afterAdd' 
methods.

An alternative would be to give the contacts themselves a 'selected' 
property.  Then you don't have to worry if the *ids* of the contacts 
change.  Just iterate over the 'selected' ones.

Another possibility is only to store Contacts as attributes of a 
PressRelease - only allow them to be added using PressRelease methods, 
not through the CMF or ZMI.

Just some ideas.  But definitely don't store copies of content objects. 
  They are redundant, can lead to inconsistencies very easily, and waste 
space.


> # available_contacts = self.aq_parent.portal_catalog(portal_type='Contact')
> # Would that limit it to Contact objects in this object's container?

no.  you would need to pass in a 'path' query as well.

http://www.zope.org/Wikis/DevSite/Proposals/PathIndexDocumentation


> Again, this seems like a framework service--am I missing something?

No, but it's hard to generalise the use case "create some type of 
user-defined relationship between two objects".  Other people have tried 
to describe the solution, and a relationship service is on the radar for 
Zope3 (somewhere).

The most general type of relationship, containment, *is* a framework 
service in a sense:  objectIds, objectValues et al are actually quite a 
flexible and useful mechanism, IMO.

seb