wtforms icon indicating copy to clipboard operation
wtforms copied to clipboard

How to implement validators that depends on multiple fields

Open cuihaoleo opened this issue 3 years ago • 1 comments

This is a question, or feature request.

I have a form in which some fields must be validated together. Below is a simplified example:

class RegistrationForm(FlaskForm):
    org_id = IntegerField("Org ID", validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    submit = SubmitField('Sign Up')

    def validate_org_id(self, field):
        org = Organization.query.get(field.data)
        if org is None:
            raise ValidationError("Invalid Org ID")

    def validate_email(self, email):
        org = Organization.query.get(self.org_id.data)  # ??
        if org is None:
            raise ValidationError("Invalid Org ID")

        email_suffix = email.data.rsplit("@", maxsplit=1)[-1]
        if email_suffix != org.domain:
            raise ValidationError("Email is not affliated with the selected org")

I want to validate:

  1. The orginization with the given org_id exists
  2. The email's domain matches the orginization's domain.

So validate_email depends on data from another field org_id. I must validate org_id as well in it. This create some duplicate code. Another choice is to skip validate_org_id and validate both in validate_email. This is not elegant -- the ValidationError would be raised in wrong position. In Flask-WTF, I would get the error rendered in wrong field.

I'm wondering what the best way to implement this kind of multi-field validators? Is it possible to tell wtforms to validate email after org_id**, so the latter one can simply assume the former field has good data in it.

cuihaoleo avatar May 24 '22 02:05 cuihaoleo

https://github.com/wtforms/wtforms/issues/55 is your answer maybe?

dgtlmoon avatar Jun 24 '22 09:06 dgtlmoon