[Zope3-Users] Re: Get classes implementing Interface

Jeff Shell eucci.group at gmail.com
Fri Dec 30 15:00:11 EST 2005


Oops. It didn't seem to provide the code. Ahhh, GMail. Not even you
can convince me that web based mail is going to replace real
clients... And if there are multiple copies of this message, I
apologize.

from zope.interface import Interface, implements
from zope.app import zapi
from zope.event import notify
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.app.container.interfaces import IAdding
from zope.app.event.objectevent import ObjectCreatedEvent
from zope.app.publisher.browser import BrowserView
from zope.app.publisher.browser.interfaces import IBrowserView

class IHomeFolderableFolder(Interface):
    """ Marker interface for home folderable folders """


class HomeFolderableFoldersAddView(BrowserView):
    """
    Note - this particular implementation is for an IAdding view. But adding
    without IAdding is not too difficult on its own.
    """
    implements(IBrowserView)
    zapi.adapts(IAdding, IDefaultBrowserLayer)

    def addableContainers(self):
        """
        Returns a sequence of mappings with the keys ``name``, ``title``, and
        ``description``. ``name`` refers to the factory name which can be used
        to create the chosen container when the form is submitted.
        """
        addable = [
            {'name': name, 'title': fact.title,'description': fact.description}
            for name, fact in zapi.getFactoriesFor(IHomeFolderableFolder)
            if fact.title
            ]
        addable.sort(key=lambda x:x['title'])
        return addable

    def action(self):
        """
        The form submission action. Looks for the factory identifier in the
        request by the name ``factory``, and calls self.createAndAdd(factory)
        with that value.
        """
        factory = self.request.form.get('factory', '')
        if not factory:
            # report error here
            return u"" # redirect back to form

        self.createAndAdd(factory)
        return self.request.response.redirect(self.nextURL())

    def createAndAdd(self, factory):
        container = zapi.createObject(factory)
        notify(ObjectCreatedEvent(container))
        # The parent of this view is IAdding, and it will actually add the
        # content to the container. If not used in an IAdding situation,
        # provide your own way of checking constraints, choosing a name, and
        # adding the object to the place it needs to go.
        container = self.context.add(container)
        # Do anything else needed here...
        return container

    def nextURL(self):
        # This just dispatches to the IAdding view's nextURL method...
        return self.context.nextURL()

> Well first (and I apologize if this has been mentioned before),
> 'containers' are a more abstract notion while 'folders' are more
> concrete. A message or document that allows comments might be a
> container, but it's not something that you'd see in the ZMI or any
> content management type interface as a folder. You'd see it as an
> article.
>
> Something that's "Folderish" (to drag up an old term) will probably
> have a folder icon, will probably (but not necessarily) will have
> sub-folders, will have a view to manage its contents, and so on.
>
> It's important to keep these concepts distinct. In our content
> management system, we have a lot of containers. Due to a lack of
> understanding on my part about when I really wanted a generic
> container versus when I wanted a folder, we had some behavioral issues
> in our code at times because generic views were being applied to the
> wrong thing. During a big refactoring sweep I just completed, I
> separated these concerns completely and made a specific marker
> interface, 'IFolderishContainer' (ahh, memories again of
> _isPrincipiaFolderish ;) that classes or interfaces had to
> _explicitly_ declare support for. I made the common Folder class that
> we were using taboo for subclassing unless one really meant to take on
> all of the responsibilities of that Folder (user interface support for
> reordering, navigation menu building, and so on). And that folder
> class, itself, does not subclass from zope.app.folder.Folder since I
> didn't want these folders to be potential site managers.
>
> So then a photo gallery or jobs folder would just declare support for
> that interface, typically in ZCML. Then they could selectively choose
> what other capabilities they wanted. And that's how we separate
> Folders from other kinds of Containers.
>
> I think that was some of the earlier questions in this thread - how to
> tell if a container is really folderish versus a more generic
> container. In the closed world of our custom applications, this is how
> I solved the problem after some painful lessons along the way.
>
> Using marker interfaces like this has been awfully helpful. I use it
> in another situation where I have a single "addMenuItem" item that
> uses a view that lists all factories that declare support for a couple
> of specific interfaces. Something like this could probably help you
> too if this is what you mean by providing a choice as to what folders
> / containers can be created. This provides data to a template via the
> 'addableContainers' method which just looks for factories for the
> IHomeFolderableContainer faux interface I made up here.
>


More information about the Zope3-users mailing list