Basic Validation¶
All elements support validation. The default, built-in validation logic is simple: if the element is empty, it is invalid. Otherwise it is valid.
If that sounds too simple don’t worry- you can customize validation to suit your needs.
Validating an Element¶
>>> from flatland import String
>>> form = String()
>>> form.is_empty
True
>>> form.valid
Unevaluated
>>> form.validate()
False
>>> form.valid
False
Validation sets the valid
attribute of each element
it inspects. validate()
may be invoked more than
once.
>>> form.set('Squiznart')
True
>>> form.is_empty
False
>>> form.validate()
True
>>> form.valid
True
Note that default validation does not set any error messages that might be displayed to an interactive user. Messages are easily added through custom validation.
Validating Entire Forms At Once¶
validate()
is recursive by default. Called on a
parent node, it will descend through all of its children, validating each. If
the parent or any one of its children are invalid, validate
returns false.
Note that recursion does not stop if it finds an invalid child: all
children are evaluated, and each will have its valid
attribute updated.
Optional Elements¶
If an element is marked as optional
, it is
exempt from validation when empty. With the default validation
strategy, this effectively means that element can never be invalid.
With custom validation, optional fields become more useful.
>>> from flatland import Dict, Integer
>>> schema = Dict.of(Integer.named('x'),
... Integer.named('y'),
... Integer.named('z').using(optional=True))
>>> form = schema(dict(x=1))
>>> form.validate()
False
>>> form.valid
True
>>> form['x'].valid
True
>>> form['y'].valid
False
>>> form['z'].valid
True
Validation Signals¶
The flatland.signals.validator_validated
signal is emitted each time a
validator evaluates an element. The signal’s sender is the validator (or the
symbol flatland.validation.NotEmpty
for the default validation
strategy). The signal also sends the element
, the state
, and the
result
of the validation function.
During development, it can be convenient to connect the
validator_validated
signal to a logging function to
aid in debugging.
from flatland.signals import validator_validated
@validator_validated.connect
def monitor_validation(sender, element, state, result):
# print or logging.debug validations as they happen:
print("validation: %s(%s) valid == %r" % (
sender, element.flattened_name(), result))
>>> from flatland import String
>>> form = String(name='surname')
>>> form.validate()
validation: NotEmpty(surname) valid == False
False