Max M wrote:
When doing sites in Zope 2 I often have the need to couple/contain two
or more fixed objects.
When an object needs to have some specific properites and logic, many
developers choose to subclass an existing object and change that.
Eg. a member folder needs to *allways* have a 'contact_info' object. Eg.
to keep company policy and to ease skinning.
That would typically lead to a new folderish content type with contact
info properties. Which I think is a really bad pattern.
Normally in Zope 2 I just give it a fixed id, and then set the
folder._reserved_names = ('contact_info',) property on the parent folder.
This is like folder.contacts_info = ContactInfo()
But this is a pretty obscure and unknown feature. And site managers
cannot use it.
I have the suspicion that many cases where people are doing Archetype
subclasses in Plone they should really use something like that approach
instead. It would lead to much simpler maintenance in the long run, with
a looser coupling of objects and less repetition of functionality.
Are there any good patterns for this in Zope 3? It would be really nice
to have a standard way of doing it.
Setup the interfaces and class, e.g.
name = FieldProperty['IContactInfo']
"""Marker interface for objects which can have IContactInfo"""
Setup an adapter from IContactable to IContactInfo. The ContactInfo
object is stored as an attribute annotation on the IContactable object.
annotations = IAnnotations(ob)
info = annotations.get('contact_info')
if info is None:
annotations['contact_info'] = info = ContactInfo()
provideAdapter(contactInfoAnnotation, [IContactable], IContactInfo)
Now *any object* which implements IContactable (and
IAttributeAnnotatable) can have ContactInfo. You access the
info = IContactInfo(ob)
info.name, info.email = u'My Name', u'[EMAIL PROTECTED]'
For example, you could even make a file object contactable,...
ob = File()
contact_info = IContactInfo(ob)
You'd more likely use ZCML class implements directives to mark which
content classes you want to be IContactable.
It would also be nice if those objects did not show up in the navigation
like folder contents. It confuses the users that they cannot delete it.
But rather "outside" the normal navigation. Like in a portlet or as a
list of actions.
The attribute annotation is not publishable. You expose it explicitly
via views. You can even combine it with the IContactable object in the
def __init__(self, context, request):
self.contact_info = IContactInfo(context)
# or maybe it should be IContactable(IContactInfo(context)) ?
From your zpt..
<span tal:replace="context/some_attr"> </span>
<span tal:replace="view/contact_info/name"> My Name </span>
It's even simpler in a formlib view, because it will automatically adapt
your context attribute similar to the above...
In Plone that is possible by adding a dot to the id like
'.contact_info', but that is a hack. Also there is no reason to have
those ugly urls.
Any pointers, or am I the only one thinking along those lines?
Have a look at Zope3 DublinCore which is done via annotations.
Zope3-users mailing list