[Framework-Team] Re: DataGridField for z3c.form?

Wichert Akkerman wichert at wiggy.net
Thu Sep 10 14:27:14 UTC 2009


I found myself having the same need as Vincent so I looked a little bit 
at z3c.form. The end result is very much a mixed blessing. As Vincent 
discovered it is not very hard to get z3c.form 2.1 to manage a list of 
items. In my example I have this interface which is repeated:

class IInformationLink(Interface):
     """A link to more information related to a risk."""

     url = schema.URI(
             title = _(u"URL"),
             required = True)
     description = schema.TextLine(
             title = _(u"Description"),
             required = False)


this has to be an Interface: if you use a zope.schema.Schema things 
break badly. You can then use this in your main interface like this:

class IRisk(form.Schema, IRichDescription, IBasic):
     """A possible risk that can be present in an organisation.
     """
     links = schema.List(
             title = _(u"Information links"),
             description = _(u"A list of links to webpages which provide"
                             u" more information on this risk."),
             required = False,
             value_type = schema.Object(
                 title = _(u"Link"),
                 schema = IInformationLink))

This works, but the resulting markup from z3c.form is quite ugly: a big 
mess of divs, nested divs, label elements inside div.label elements, 
etc. The UI it presents is also very confusing: 
https://photos-1.getdropbox.com/i/o/JmLD1SNVPJbwy12pgo-FYOWLsG-9L9lKNdBCm6yIfok 
is an example. Notice how it is very unclear that the Add/Remove buttons 
at the button belong to the 'Links' field. It gets even worse if you try 
to insert some data: 
https://photos-1.getdropbox.com/i/o/ZrPquRJE5oEOZn1DhCdS6ZTDArNqKhAZ15UGtF-3sqA 
. Part of this is a flaw in zope.schema which does not except URLs 
without a http: prefix (which will confuse users). The 'The system could 
not process the given value' is a mysterious one and reveals an 
essential bit that is not documented: z3c.form requires a IObjectFactory 
factory for the IInformationLink interface. This is an multi-adapter 
(with 4 facets, almost none of which you will ever need) and requires 
the name of the adapter to be set to the interface (feels like ZCA abuse 
to me):

from zope.interface import Interface
from zope.interface import implements
from zope.component import adapts
from z3c.form.interfaces import IObjectFactory

class InformationLinkFactory(object):
     adapts(Interface, Interface, Interface, Interface)
     implements(IObjectFactory)

     def __init__(self, context, request, form, widget):
         pass

     def __call__(self, value):
         return dict(value)

which you can register in zcml like so:

     <adapter factory=".risk.InformationLinkFactory"
       name="euphorie.content.risk.IInformationLink" />

and then it still does not work since it requires that your object 
factory returns something that zope.schema.Object can handle. In other 
words: it is not possible to return dictionaries.

Next attempt: use a simple object that can implement IInformationLink:

class InformationLink(object):
     implements(IInformationLink)

     def __init__(self, value):
         self.url=value["url"]
         self.description=value["description"]


class InformationLinkFactory(object):
     adapts(Interface, Interface, Interface, Interface)
     implements(IObjectFactory)

     def __init__(self, context, request, form, widget):
         pass

     def __call__(self, value):
         return InformationLink(value)


and that finally works. The lessons I have learned from this are:

- z3c.form produces very awful HTML
- z3c.form produces very confusing user interfaces
- z3c.form documentation is indeed incomplete (no mention of
   ObjectFactory)
- z3c.form you can do cool stuff with it, although I am not convinced
   it is much better than hand-coding the form

And the reason I cc'ed the framework team: I strongly feel that until 
the generated markup and user interfaces from z3c.form are improved to 
meet Plone standards Plone itself should start using it.

Wichert.




More information about the Framework-Team mailing list