libreForms / libreForms-flask

Flask implementation of the libreForms API
https://libreforms.readthedocs.io
GNU Affero General Public License v3.0
4 stars 1 forks source link

[forms] add backend form field validation to wtforms #416

Open signebedi opened 1 year ago

signebedi commented 1 year ago

[forms] add backend form field validation to wtforms Now that we are moving toward using wtforms, we should also add back end form validation to supplement the front end field validation that we implemented in #380.

Originally posted by @signebedi in https://github.com/libreForms/libreForms-flask/issues/30#issuecomment-1537166353

signebedi commented 1 year ago

To validate form fields in a manner similar to define_webarg_form_data_types, you can update the create_dynamic_form function to use the lambda functions for validators.

First, modify the create_dynamic_form function to include the validators:

def create_dynamic_form(form_name, user_group, form_args, libreforms, checkGroup):
    ...
    for field, field_config in form_fields.items():
        validators = []
        if field_config.get('validators'):
            for validator in field_config['validators']:
                validators.append(validator)
        setattr(FormClass, field, field_class(**field_kwargs, validators=validators))
    ...

Now, when creating the form instance in your view function, you can use the validate() method to check if the form is valid:

if form_instance.validate():
    parsed_args = form_instance.data
else:
    flash("Form validation failed. Please correct the errors and try again.", "warning")
    return render_template('app/forms.html.jinja', form=form_instance, ...)  # Add other required arguments

When calling validate(), it will run the lambda functions (validators) for each field, and if there are any errors, they will be stored in the errors attribute of the corresponding form field.

In your Jinja2 template, you can display the errors as mentioned in the previous response:

{{ form_instance.field_name.label }}: {{ form_instance.field_name }}
{% if form_instance.field_name.errors %}
    <ul>
    {% for error in form_instance.field_name.errors %}
        <li>{{ error }}</li>
    {% endfor %}
    </ul>
{% endif %}

Replace "field_name" with the actual name of the form field in your template.