[<<] Industrie Toulouse

A significant design choice of Zope 3 is that it's interface driven. Interfaces are used not only to document, but to adapt. Interfaces are Zope 3's type system. Unlike class based types, anything can implement them or adapt to them, and all proper code in the Zope 3 system should ask for an interface implementation for a given object.

Interface design has been taken beyond basic method definitions to include object schema and even pre / post conditions. This data can be introspected to build user interfaces, which is how much of the standard Zope 3 management interface gets built. In fact, I'll show how this is done next in the series.

So the basic todo application uses the following interfaces. These are just the basic model objects. The Todo List is just a container that only contains items that implement the ITodo interface. A Todo doesn't do much beyond store some simple data. So here they are, from the file 'interfaces.py' in the package 'todo':

from zope.interface import Interface
import zope.schema

# These will aid in making a special "todo" container by specifying the
# constraint in the interface.
from zope.app.container.constraints import ItemTypePrecondition
from zope.app.container.interfaces import IContained, IContainer

class ITodo(Interface):
    """ A todo item doesn"t need to do much... """ 
    description = zope.schema.TextLine(
        title=u"To Do",
    details = zope.schema.Text(

    done = zope.schema.Bool(title=u"Done")

class ITodoList(IContainer):
    """ A todo list contains todo objects.  """
    def __setitem__(name, object):
        """ Add an ITodo object. """

    __setitem__.precondition = ItemTypePrecondition(ITodo)

The implementation is even simpler. Since this is a small application, I put the implementation in todo/__init__.py:

from zope.interface import implements
from zope.app.container.btree import BTreeContainer
from persistent import Persistent

from interfaces import ITodoList, ITodo

class TodoList(BTreeContainer):

class Todo(Persistent):

    description = u""
    details = u""
    done = False
And that's it. Really! Now what needs to be done next is to wire these into Zope 3. But already, one can see that this is much simpler than what one might have to do to write some data objects for Zope 2.