Suppose we have a form in which two inputs need to be the same, i.e.: email matching or password matching.
import formencode from formencode import validators as v class Registration(formencode.Schema): email_input = v.Email(strip=True, resolve_domain=True) email_input_confirm = v.Email(strip=True, resolve_domain=True) chained_validators = [v.FieldsMatch("email_input", "email_input_confirm")]
chained_validators runs after all other validators inside of
Registration is done. v.FieldsMatch will verify that the two given
fields match with each other.
If we have a input field which expect a user input a integer in
between 0 and 99. When we get the input in the backend, it's always a
string. Before we need to validate using OneOf, we need to convert
the input from string to int via Int.
import formencode from formencode import compound as c from formencode import validators as v class Calculator(formencode.Schema): # All validates backwards numerator = c.All(v.OneOf(range(100)), v.Int()) # Pipe validates forwards # numerator = c.Pipe(v.Int(), v.OneOf(range(100)))
Now suppose we have a form with a group of employees. Each employee
has his/her own first name, last name, email, and phone number. In the
frontend, a user can add a new employee or delete an existing
employee. In another word, we don't know how many employees ahead we
are going to validate. Thus, we can not use Brute-force validation
like we did before. Formencode provides a function called
formencode.ForEach which helps us solve similar problems.
Here is how our form looks like:
<form> <table> <tr> <td><input type="text" name="employee-0.first_name"></td> <td><input type="text" name="employee-0.last_name"></td> <td><input type="text" name="employee-0.email"></td> <td><input type="text" name="employee-0.phone"></td> </tr> <tr> <td><input type="text" name="employee-1.first_name"></td> <td><input type="text" name="employee-1.last_name"></td> <td><input type="text" name="employee-1.email"></td> <td><input type="text" name="employee-1.phone"></td> </tr> <tr> <td><input type="text" name="employee-2.first_name"></td> <td><input type="text" name="employee-2.last_name"></td> <td><input type="text" name="employee-2.email"></td> <td><input type="text" name="employee-2.phone"></td> </tr> ... </table> </form>
The validation class definition will be
import formencode from formencode import validators as v from formencode import national as n class Employee(formencode.Schema): first_name = v.String(strip=True) last_name = v.String(strip=True) email = v.String(strip=True, resolve_domain=True) phone = n.USPhoneNumber() class Employees(formencode.Schema): employee = formencode.ForEach(Employee())