> So my question is simple : how do I have to handle such custom
> constraints, which are applied to only one field and which I don't want
> to define via invariants (because I'd like the error message to be
> displayed correctly next to the required widget) ?
> Until now I've tried a few methods (via "widget._error" property for
> example) not nothing gave me correct results...
1. You may use __call__ method of your form (view) to create field
as required or not required depending on parameters. Creating individual
fields is described in formlib.txt

2. widget._error
In validation function or in action handler function you may set
widget._error for field. I've created function for this like:

    from zope.app.form.interfaces import WidgetInputError

    def setWidgetError(self, name, v):
        """ Helper function for validation purposes.
            Sets error for widget
             @name - field name
             @v - error message
        w = self.widgets.get(name)
        if w:
            w._error = WidgetInputError(
              self.context.__name__, w.label, v)
        return w._error

You may use this function in success handler method like:

if not data['myfield']:
    error = self.setWidgetError('myfield', 'Required field is empty')
    self.form_reset = False

To avoid setting form_reset etc. I am using slightly modified
implementation of formlib's update function (but you don't have to do
it). Original is like:

        if errors:
            self.status = _('There were errors')
            result = action.failure(data, errors)
        elif errors is not None:
            self.form_reset = True
            result = action.success(data)
            result = None

        self.form_result = result

action.success method is the one that has filled data dictionary
passed as parameter. In opposite, validate function only gets empty
data dictionary. So it becomes natural to do some validation in
success handler (although it is possibly not supposed to be done here?).
More, if for example succes handler function does
insert or update to a RDBMS wchich may cause some errors (or receive
error message from stored procedure etc.) it is desirable to set form
errors too. My modified update method is like:

        if errors:
            self.status = _('There were errors')
            result = action.failure(data, errors)
        elif errors is not None:
            result = action.success(data)
            if not self.errors:
                self.form_reset = True
                self.status = _('There were errors')
                result = action.failure(data, errors)
            result = None

Maciej Wisniowski
Zope3-users mailing list

Reply via email to