How do I validate in datagridfield?

What is the 'correct way' to validate DataGridfields ?

In 'normal field', I can validate with

def company_letter_kodeConstraint(value):
    """Check that the company_3 letter code is upperclass
    """
    if not value.isupper():
        #Does not work with datagridfield, gives error in browser
        raise Invalid(_(u"Only capital letters for Company 3 letter code"))
        #Works with datagridfield, but will show error message 'Constraint not satisfied /The system could not process the given value.'
        return False
    return True

UPDATE: This might be due to 'bootstrap stuff', because the following works (but will return the error message)

def company_letter_kodeConstraint(value):
"""Check that the company_3 letter code is upperclass
"""
if not value.isupper():
raise InvalidValue()
#raise InvalidValue(_(u"This message will not show "))
return True

I'm running into the same issue I think, in Plone 5.2, DGF 1.5.3.

def filesize_limit(data, limit=5):
    mbs = data.size/1024/1024
    if mbs > limit:
        raise Invalid(f'File must not exceed {limit} MB')

def validate_presentation(val):
    filesize_limit(val, 5)

class IPresentation(model.Schema):
    file = NamedBlobFile(
        title='Attachment',
        description='If available, upload an image of the presenter(s) at the event or a flyer '
                    'of the event (less than 5 MB).',
        required=False,
        constraint=validate_presentation
    )

class IMySchema(model.Schema):
    directives.widget(presentations=BlockDataGridFieldFactory)
    presentations = schema.List(
        title='Presentations',
        value_type=DictRow(title="Presentation", schema=IPresentation),
        required=False,
    )

In the Dexterity add form, if I set the schema just to IPresentation (no DGF) it works as expected. With the schema set IMySchema, validation fails but instead of being caught and a warning shown it just displays the traceback.

I tried raising a ValidationError instead. This led to the message "The system could not process the given value." on the presentations field and "Raised if the Validation process fails." on the presentations sub field.

I also tried setting a constraint on the DGF field itself (presentations) but the method was never reached.

Here's one solution, though not ideal: remove constraints from the schema and validate instead on the form's handler.

def validate_presentation(val):
    if not filesize_limit(val['file'], 5):
        raise WidgetActionExecutionError('presentations',
                                         Invalid(f'File size must not exceed 5 MB'))
...

    @button.buttonAndHandler(_("Save"), name="save")
    def handleAdd(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return
        for presentation in data['presentations']:
            validate_presentation(presentation)

Not ideal, as it highlights the entire DGF.

edit:
This doesn't work if I move the field "presentations" into a fieldset. Ideally I still want to assign validation directory to a schema field anyway.

It looks to me that it is possible to use InvalidValue() ONLY if the other fields does not have any 'normal validation present'.

In other words:

  • validation and raise InvalidValue() works for 'field A', but does not give 'proper error message'.

  • if we add in field B

    fieldB = schema.TextLine(
    max_length=3,

things 'break'


Will report back if / when I find out more

Here's another DGF validation snippet