Invariant between behaviors? (DX/z3cform)

z3cform/ dexterity question:

I have a custom behavior A with a field myfield.

Now I want an invariant validation to have this field required only (or some other validation) if
otherfield on an other behaviour B was set.

In my invariants 'data' on A does not contain 'otherfield' (only myfield).

How can i access the values from behavior B in my invariant on behavior A?

Use the request data directly, ie http://docs.plone.org/develop/plone/serving/http_request_and_response.html#zope-globalrequest-getrequest

Ok, this may work, but is a kind of ugly workaround.

I dont understand why data does not contain the complete already extracted values.
After digging deeper it looks like the form groups and how the are build in plone.autoform are the problem?

If schema-level validation is not possible, is there a hook to do invariants on form-level?

By default, invariant validators can only validate values within the same schema. This limitation comes all the way from zope.interface.

A real design mistake might be that, in z3c.form, data extraction is tighly integrated with validation, thus, calling data extraction within any validator could cause infinite recursion.

Anyway, if you know, what to look for, you can manually extract the field you need for the validation:

zcml:

<adapter factory=".behaviors.MyValidator" />

py:

from z3c.form import validator
from zope.interface import Invalid

class MyValidator(validator.SimpleFieldValidator):

    def validate(self, value):
        fieldsets = dict([(group.__name__, group)
                          for group in self.widget.form.parentForm.groups])
        other_value = fieldsets['myfieldset'].widgets['otherfield'].extract()
        # ...
        raise Invalid('Validation error')

validator.WidgetValidatorDiscriminators(MyValidator, field=IMyBehavior['myfield'])

I agree that it's unfortunate, that you need to know, in which fieldset the dependent field is and what's its complete name (prefixed with the behavior interface).

2 Likes