[Zope3-Users] problems with contains and containers

Lorenzo Gil Sanchez lgs at sicem.biz
Tue Mar 21 13:21:25 EST 2006


Just for the record, the following implementation works:

from persistent import Persistent
from zope.schema import Field
from zope.app.container.interfaces import IContainer, IContained
from zope.app.container.constraints import contains, containers
from zope.app.container.contained import Contained
from zope.app.container.btree import BTreeContainer
from zope.interface import implements, Interface
from zope.app.container.constraints import ContainerTypesConstraint
from zope.app.container.constraints import ItemTypePrecondition

class IMyContent(Interface):
    pass

class IMyContainer(IContainer):
    def __setitem__(name, object):
        pass

    __setitem__.precondition = ItemTypePrecondition(IMyContent)

class IMyContentContained(IContained):
    __parent__ = Field(
        constraint = ContainerTypesConstraint(IMyContainer))

class MyContent(Persistent, Contained):
    implements(IMyContent, IMyContentContained)

class MyContainer(BTreeContainer):
    implements(IMyContainer)

El mar, 21-03-2006 a las 19:10 +0100, Lorenzo Gil Sanchez escribió:
> Hi,
> 
> I have a custom container and a custom content type and I want to make
> some simple restrictions:
> 
> - Only objects that implement IMyContent can be added to objects that
> implement IMyContainer
> 
> - Only objects that implement IMyContainer can contain objects that
> implement IMyContent
> 
> Looks like the typical example. I implemented it following Stephan book
> instructions and it worked well. The only issue was that I was getting
> the feeling that splitting the interface in two and having something
> like IMyContent, IMyContentContained was a little bit ugly.
> 
> Then I read about 'contains' and 'containers' and that they allowed me
> to keep the interfaces together because I could use strings as their
> arguments with the path for the other interfaces. Much nicer indeed. So
> here is my little demo code:
> 
> from persistent import Persistent
> from zope.app.container.interfaces import IContainer, IContained
> from zope.app.container.constraints import contains, containers
> from zope.app.container.contained import Contained
> from zope.app.container.btree import BTreeContainer
> from zope.interface import implements
> 
> class IMyContent(IContained):
>     containers('.IMyContainer')
> 
> class IMyContainer(IContainer):
>     contains(IMyContent)
> 
> class MyContent(Persistent, Contained):
>     implements(IMyContent)
> 
> class MyContainer(BTreeContainer):
>     implements(IMyContainer)
> 
> And in my browser package I have defined add views for both content
> types. Then I start Zope and create an instance of MyContainer in the
> root folder. I go into this objects and in the right hand add menu I see
> the only object I can add is MyContent. So far so good. The problem is
> when I try to get to the add form of MyContent. I get this error:
> 
> 2006-03-21T18:58:13 ERROR SiteError http://localhost:8080/a/@@
> +/action.html
> Traceback (most recent call last):
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/publisher/publish.py", line 138, in publish
>     result = publication.callObject(request, object)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/app/publication/zopepublication.py", line 161, in callObject
>     return mapply(ob, request.getPositionalArguments(), request)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/publisher/publish.py", line 113, in mapply
>     return debug_call(object, args)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/publisher/publish.py", line 119, in debug_call
>     return object(*args)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/app/container/browser/adding.py", line 128, in action
>     name=view_name) is not None:
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/component/__init__.py", line 165, in queryMultiAdapter
>     return sitemanager.queryMultiAdapter(objects, interface, name,
> default)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/component/site.py", line 75, in queryMultiAdapter
>     default)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/interface/adapter.py", line 475, in queryMultiAdapter
>     return factory(*objects)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/app/form/browser/editview.py", line 64, in __init__
>     self._setUpWidgets()
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/app/form/browser/add.py", line 49, in _setUpWidgets
>     setUpWidgets(self, self.schema, IInputWidget, names=self.fieldNames)
>   File "/home/lgs/zope/Zope-3.2/lib/python/zope/app/form/utility.py",
> line 153, in setUpWidgets
>     context=context)
>   File "/home/lgs/zope/Zope-3.2/lib/python/zope/app/form/utility.py",
> line 97, in setUpWidget
>     widget = _createWidget(context, field, viewType, view.request)
>   File "/home/lgs/zope/Zope-3.2/lib/python/zope/app/form/utility.py",
> line 65, in _createWidget
>     return zapi.getMultiAdapter((field, request), viewType)
>   File
> "/usr/local/src/Zope-3.2.0/build/lib.linux-i686-2.4/zope/component/__init__.py", line 154, in getMultiAdapter
>     raise ComponentLookupError(objects, interface, name)
> ComponentLookupError: ((<zope.schema._bootstrapfields.Field object at
> 0xb52e44ec>, <zope.publisher.browser.BrowserRequest instance
> URL=http://localhost:8080/a/@@+/action.html>), <InterfaceClass
> zope.app.form.interfaces.IInputWidget>, u'')
> 
> And it didn't happen with my old code with splitted interfaces.
> 
> Any idea?
> 
> thanks in advance
> 
> Lorenzo Gil
> 
> _______________________________________________
> Zope3-users mailing list
> Zope3-users at zope.org
> http://mail.zope.org/mailman/listinfo/zope3-users
> 



More information about the Zope3-users mailing list