On Jan 30, 2006, at 3:21 AM, Michael Howitz wrote:

Hi, as suggested in #zope3-dev I'll post my experiences with interface
invariants and formlib here.

I have an interface with two password fields which should be equal:

class IUser(Interface):
    password2=zope.schema.Password(title=u"password again")

# this Exception is raised when password are not equal
class PasswordsAreNotEqual(zope.schema.ValidationError):
    u"""Passwords are not equal."""
    # the docstring is shown in UI becuase it is a ValidationError
    # see below why

# this function tests equality
def arePasswordsEqual(obj)
    if obj.password != obj.password2:
        raise PasswordsAreNotEqual

# set the test function as invariant
IUser.setTaggedValue('invariants': [arePasswordsEqual])

You may already be aware of this and rejecting it for religious reasons, but it is arguably easier to do this by defining it in the interface, either with an "@invariant" or "arePasswordsEqual = invariant(arePasswordsEqual)" (invariant as imported from zope.interface and defined in zope.interface.interface).

Formlib expects Errors raised by invariants to be subclasses from
zope.interface.Invalid (which zope.schema.ValidationError is).

That constraint is actually defined in zope.interface, fwiw.

To dislay the error formlib tries to get a multi adapter which provides
zope.app.form.browser.interfaces.IWidgetInputErrorView. There is only
one such adapter in Zope3

Yes; generally, we define our own views.

(zope.app.form.browser.exception.WidgetInputErrorView) because it seems
that all other errors in FormBase's self.errors are implementing
zope.app.form.interfaces.IWidgetInputError or even they are instances of
zope.app.form.interfaces.WidgetInputError. (Did not try.)

So I implemented zope.app.form.interfaces.IWidgetInputError in my error
class. (Which really implements this interface because the only method
the interface provides (doc) is implemented by

If the exception has an attribute widget_title (which is not in the
interface zope.app.form.interfaces.IWidgetInputError but only in the
class zope.app.form.interfaces.WidgetInputError) then the value of this
attribute is displayed in front of the error message separted by a

That's arguably a bit of a hack: these aren't widget errors. But it's a reasonable prototype decision.

The error message is only displayed on the top of the form. Maybe there
is also a way to get the error message displayed under a widget.

Not currently; the exception would have to have some data to help this. We don't do this, and formlib doesn't help with it, but it would be a nice option.

Is this the way it should be done?

As above.

Zope3-dev mailing list
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com

Reply via email to