[Zope] ObjectManager 'Contents' problem

John Hunter jdhunter@ace.bsd.uchicago.edu
Mon, 06 May 2002 18:05:15 -0500


I am working on two demo classes in a Product, a Person and an
Address.  Both are derived from SimpleItem, and Person is also derived
from ObjectManager, because I want it to be able to contain an Address
in a Person.

Here is my problem:

 When I add an Address instance to a Folder, all works as expected, so
 I think the Address constructor and class are ok.

 When I add an Address instance to an instance of my Person, zope
 accepts it fine (no errors) but the instance does not show up in the
 Contents view, which displays the message 'There are currently no
 items in me' where 'me' is the id of the Person instance .  If I try
 to add another address with the same id, I get an error saying the id
 is already in use.  But I cannot see the Address instance, even if I
 call a method like

    <dtml-in "PARENTS[0].objectValues()">
	   <h3><dtml-var id>:</h3>
    </dtml-in>

 on the person instance.  

I would appreciate any advice.  I don't give a whit about persons or
addresses, but plan to use this code as a template for my actual
development, so I'm also happy to hear any criticism of the code
below.  I am using the Component/Interface design suggested in the
Zope Dev Guide, and have based on lot of the code on maxm's HOWTOs and
mxm classes

Thanks,
John Hunter

######### Person.py -- the person interface ##################

from Interface import Base

class Person(Base):
    "A person is a person, no matter how small"
    def getFullName(self):
        "Return full name"


    


######### PersonImplemetation.py ##################

from Person import Person
import Products
from AccessControl import ClassSecurityInfo
from Globals import DTMLFile, InitializeClass
from OFS.SimpleItem import SimpleItem
from OFS.PropertyManager import PropertyManager
from OFS.ObjectManager import ObjectManager

class PersonImplementation(SimpleItem, PropertyManager, ObjectManager):
    """
    Person product class, implements Person interface.
    """

    __implements__=Person

    meta_type='Person'
    security=ClassSecurityInfo()

    _properties=({'id':'first', 'type': 'string', 'mode': 'w'},
                 {'id':'last', 'type': 'string', 'mode': 'w'},
                 )

    _allowed_meta_types = ('Address', )
    
    manage_options = (
        (ObjectManager.manage_options[0],)+
        PropertyManager.manage_options + 
        SimpleItem.manage_options + 
        (
        { 'label' : 'View', 'action' : 'index_html', },
        )
        )



    security.declarePublic('index_html')
    #security.declareProtected('View management screens', 'index_html') 
    index_html=DTMLFile('www/person/index_html', globals())

    def __init__(self, id, first, last):
        self.id=id
        self.first = first
        self.last = last

    security.declarePublic('getFullName') 
    def getFullName(self):
        "Return full name"
        return '%s %s' % (self.first, self.last)

    def all_meta_types(self):
        """
        Returns what meta_types can be added to the objectmanager
        """
        if hasattr(self, '_allowed_meta_types'):
            result = []
            for metaType in Products.meta_types:
                if metaType['name'] in self._allowed_meta_types:
                    result.append(metaType)
            return result
        else:
            return Products.meta_types

def addPersonForm(dispatcher):
    """
    Returns an HTML form.
    """
    return """<html>
    <head><title>Add Person</title></head>
    <body>  
    <form action="addPersonFunction">
    id <input type="type" name="id"><br>
    first <input type="type" name="first"><br>
    last <input type="type" name="last"><br>
    <input type="submit" value="Add">
    </form>
    </body>
    </html>"""

def addPersonFunction(dispatcher, id, first, last, REQUEST=None):
    """
    Create a new person and add it to myself
    """
    n=PersonImplementation(id, first, last)
    dispatcher.Destination()._setObject(id, n)

    if REQUEST is not None:
        return dispatcher.manage_main(dispatcher, REQUEST)

InitializeClass(PersonImplementation)

######### Address.py -- the interface ##################

from Interface import Base

class Address(Base):
    "Where to find me"
    def getAddress(self):
        "Return full address"

######### AddressImplemetation.py ##################

from Address import Address
from AccessControl import ClassSecurityInfo
from Globals import DTMLFile, InitializeClass
from OFS.SimpleItem import SimpleItem
from OFS.PropertyManager import PropertyManager

class AddressImplementation(SimpleItem, PropertyManager):
    """
    Address product class, implements Address interface.
    """

    __implements__=Address

    meta_type='Address'

    security=ClassSecurityInfo()

    _properties=({'id':'street', 'type': 'string', 'mode': 'w'},
                 {'id':'city', 'type': 'string', 'mode': 'w'},
                 {'id':'state', 'type': 'string', 'mode': 'w'},
                 {'id':'zip', 'type': 'string', 'mode': 'w'},
                 )

    manage_options = \
                   PropertyManager.manage_options + \
                   SimpleItem.manage_options + \
                   (
        { 'label' : 'View', 'action' : 'index_html', },
        ) 


    security.declarePublic('index_html')
    #security.declareProtected('View management screens', 'index_html') 
    index_html=DTMLFile('www/address/index_html', globals())

    def __init__(self, id, street, city, state, zip):
        self.id=id
        self.street = street
        self.city = city
        self.state = state
        self.zip = zip

    security.declarePublic('getAddress') 
    def getAddress(self):
        "Return full address"
        return '%s\n%s, %s %s' % (self.street, self.city, self.state, self.zip)


def addAddressForm(dispatcher):
    """
    Returns an HTML form.
    """
    return """<html>
    <head><title>Add Address</title></head>
    <body>  
    <form action="addAddressFunction">
    id <input type="type" name="id"><br>
    street <input type="type" name="street"><br>
    city <input type="type" name="city"><br>
    state <input type="type" name="state"><br>
    zip <input type="type" name="zip"><br>
    <input type="submit" value="Add">
    </form>
    </body>
    </html>"""

def addAddressFunction(dispatcher, id, street, city, state, zip, REQUEST=None):
    """
    Create a new address and add it to myself
    """
    n=AddressImplementation(id, street, city, state, zip)
    dispatcher.Destination()._setObject(id, n)
    if REQUEST is not None:
        return dispatcher.manage_main(dispatcher, REQUEST)

InitializeClass(AddressImplementation)


############### Product __init__.py #####################

from PersonImplementation import PersonImplementation, addPersonForm, addPersonFunction
from AddressImplementation import AddressImplementation, addAddressForm, addAddressFunction

def initialize(registrar):
    registrar.registerClass(
        PersonImplementation,
        constructors = (addPersonForm, addPersonFunction),
        icon="www/images/User_icon.gif",
        )

    registrar.registerClass(
        AddressImplementation,
        constructors = (addAddressForm, addAddressFunction),
        )