[Zope3-Users] Re: Compound Form Elements

Duncan McGreggor duncan.mcgreggor at gmail.com
Thu Oct 6 05:10:16 EDT 2005


On Oct 6, 2005, at 2:29 AM, James Allwyn wrote:

> On 04/10/05, James Allwyn <jamesallwyn at gmail.com> wrote:
>
>> Hello,
>>
>> I wish my users to be able to register various contact details. For
>> each, I would record the type (e.g. email, landline tel, mobile tel,
>> fax...), the value (e.g. test at email.com) and a True/False value on
>> whether it is to be visible on the site.
>
> I've tried to implement this zopeishly, and the stumbling block I've
> hit seems to be specifying the key and value_type pairs in the dict.
> So, for example:

[snip]

> This barfs when it hits the second value_type in the dict. Look at the
> zope.schema sources it seems I can only specify one value_type and one
> key_type. What I want to do is specify three pairs of keys and
> value_types - note, specifying the actual keys, not just their types.
> Is this possible? Or am I barking up the wrong tree!?
>
> Any hints gratefully received.

Hey James,

What you probably want to explore is the "Object" field. This lets you 
define a "sub-schema", as it were, and use that in your "main" schema. 
An example (untested)... maybe in yourproject/types/interfaces.py:

from zope.interface import Interface
from zope.schema import List, Text, TextLine, Int, Choice
from zope.schema import Object

from zope.i18nmessageid import MessageIDFactory
_ = MessageIDFactory('yourproj')

# sub-schema
class IContactData(Interface):
   show = Bool(title = _(u"Show Data?"))
   type = TextLine(title = _(u"Data Type"))
   value = TextLine(title = _(u"Data Value"))

# main schema
class IUser(Interface)
   name_first = TextLine(
     title = _(u"First Name")
   )
   name_last = TextLine(
     title = _(u"Last Name")
   )
   contact_info = List(
     title = _(u"Contact Info"),
     value_type = Object(
       schema=IContactData,
     ),
   )

Then (maybe in user.py, ):

...
class ContactData(object):
     implements(IPageSection)
     # and whatever else you might want to
     # put in here

class User(PortalContent):
     implements(IUser)
     # and whatever else you might want to
     # put in here
...

Then you're going to have to do some extra work with a custom widget (a 
good place would be ./browser/userview.py):

from zope.app.form.browser import ObjectWidget
from zope.app.form.browser.editview import EditView
from zope.app.form import CustomWidgetFactory

from yourproject.types import ContactData
from yourproject.types.interfaces import IUser

parts_w = CustomWidgetFactory(ObjectWidget, ContactData)

class ContactDataEditView(EditView):
     """
     View for editing a page section.
     """
     __used_for__ = IUser

     parts_widget = parts_w


In your browser/configure.zcml, your going to need something like this:

   <browser:editform
       schema="yourproject.types.interfaces.IUser"
       class=".userview.ContactDataEditView"
       label="Edit User"
       name="edit.html"
       menu="zmi_views"
       title="Edit"
       permission="zope.ManageContent" />

I may be forgetting something here... but this should certainly give 
you a head start. There's a bunch of very good information on this in 
these files:

zope/app/form/browser/widgets.txt
zope/app/form/browser/objectwidget.txt

Hmmm, looking through these again, these are really good examples. Pay 
more attention to them than to what I wrote above ;-)

By the way, (and irrespective of the structure of the data) this data 
you are adding seems to me a good candidate for annotations. You might 
want to explore that...

Happy trails!

d



More information about the Zope3-users mailing list