Saturday, 28 May 2022

How to handle error messages when validating a form across different FieldLists of FormFields?

I have a form that contains (among other fields) 2 FieldLists. Each FieldList is a list of FormFields. In each FieldList, the forms all represent projects. One fieldlist is for projects having budget taken away, and the other list is for projects that will be the recipients of that budget. This is a dynamic form; there can be an arbitrary number of deallocations or allocations. There will be a lot of validations in the overall form, but a simple case that I cannot get working is making sure no project appears twice in the form (that is to say that across both lists, project IDs must be unique). I can test for this and recognize when this situation occurs, but I am having trouble associating error messages with the offending project IDs.

A simplified version of my form classes is:

class AllocationForm(Form):
    project_id(StringField, label='Project ID')
    ... details about amount being allocated here

class DeallocationForm(Form):
    project_id(StringField, label='Project ID')
    ...details about amount being deallocated here

class RequestForm(FlaskForm):

    def validate(self):

        project_id_seen = {}
        project_list = [a for a in self.allocations] + [d for d in self.deallocations]

        for formfield in project_list:
            if project_id_seen.get(formfield.data.get('project_id')) is None:
                project_id_seen[formfield.data.get('project_id')] = 1
            else:
                # *** Here's where I'm having an issue ***
                somethingsomethingsomething['project_id'] = 'A project ID cannot appear more than once in a request'
                return False

        # other form validations happen here
        if not FlaskForm.validate(self):
            return False

    allocations = FieldList(FormField(AllocationForm))
    deallocations = FieldList(FormField(DeallocationForm))

As you can see, I'm overriding RequestForm's validate method. Where I return False in the else clause, I'd like to associate an error message with the project ID in question so that I can display it when the form is re-rendered, but I'm having difficulty accessing the specific project_id field in the subform. Any ideas?

EDIT: It occurs to me that another approach might be to put validators on the project ID fields in the AllocationForm and DeallocationForm classes instead of RequestForm. Is this a more feasible approach? Associating the error message with the field would be easier, but how would the validator in AllocationForm access the project IDs in DeallocationForm and vice versa?



from How to handle error messages when validating a form across different FieldLists of FormFields?

No comments:

Post a Comment