Collective.z3cform.datagridfield ignoring required=True or how to add extra validators to a Dexterity edit/add form?

I have a DX content-type with a datagridfield (specified using plone.supermodel).

<field name="fonds" type="zope.schema.List">
  <description>Fonds des Titelverwalters</description>
  <title>Fonds</title>
  <value_type type="collective.z3cform.datagridfield.DictRow">
    <schema>zchl.policy.interfaces.IFondsSchema</schema>
  </value_type>
  <form:widget type="collective.z3cform.datagridfield.DataGridFieldFactory"/>
  <required>True</required>
</field>

Unfortunately the required=True setting is ignored upon adding/saving the add/edit form.

Where takes the validation for 'required' place? Or is it possible to add a custom validator to the auto-generated add/edit forms for DX content?

-aj

Either set <min_length>1</min_length>, or set missing_value= so that an empty list is counted as a missing value. I'm not sure there's a way to do the latter in supermodel XML -- <missing_value></missing_value> may be interpreted as None -- so try the former.

You can write a custom field validator like this:

from z3c.form import validator
from zope.interface import Invalid
class CustomValidator(validator.SimpleFieldValidator):
    def validate(self, value):
        super(CustomValidator, self).validate(value)
        if value:
            if [value is not valid]:
                raise Invalid(u'Value is not valid')

And use it from supermodel XML like this:

form:validator="dotted.path.to.CustomValidator"

Note that a validator specified in this way overrides the default z3c.form field validator, so it's important to remember to call super().validate.

1 Like

(Note: edited my previous reply to escape markup that Discourse ate.)

Unless I am understanding incorrectly, setting missing_value to a mutable collection type might have some shared-state side-effects, if you are not careful?

For forms, likely not a big deal because a round-trip through data converters cleans this up, but if you construct an item programmatically, I suppose there is a possibility of having multiple instances of content reference the same list.

Since this is a list, not a PersistentList, Persistence round-trip can also incidentally reduce likelihood of accidentally sharing state (post-commit, across threads), but I have been bit more than once by using a mutable collection as a default for a schema field (defaultFactory=list might work better?).

Sean

Good point, Sean. I was thinking narrowly about how zope.schema compares the value to the field's missing_value during "required" validation, but not about the other implications of specifying a list here.

Thanks, this worked.

-aj