Feature Guide
import respect_validation
In most cases you need only Validator. It will be handy to import it just like one letter "v":
Simple validation
The Hello World validator is something like this:
Chained validation
It is possible to use validators in a chain. Sample below validates a string containing numbers and letters, no whitespace and length between 1 and 15.
username_validator = v.alnum().noWhitespace().length(1, 15)
username_validator.validate('alganet') # true
Validating object attributes
Given this simple object:
class User(object):
pass
user = User()
user.name = 'Alexandre'
user.birthdate = datetime('1987-07-01', '%Y-%m-%d')
It is possible to validate its attributes in a single chain:
# "name" in between 1 to 32 symbols
# "birthdate" older than 18 years old
user_validator = v.attribute('name', v.stringType().length(1, 32)). \
attribute('birthdate',
v.date().Max(datetime(datetime.now().year - 18, datetime.now().month, datetime.now().day)))
user_validator.validate(user) # true
Validating dictionary is also possible using v.key()
Note that we used v.stringType()
and v.date()
in the beginning of the validator.
Although is not mandatory, it is a good practice to use the type of the
validated object as the first check in the chain.
Validating dictionaries
Validating dict into another dict is also possible using Key.
If we got the dict below:
Using the next combination of rules, we can validate child keys.
v.key(
'parentKey',
v.key('field1', v.stringType()).\
key('field2', v.stringType()).\
key('field3', v.boolType())
)\
.claim(data) # You can also use check() or validate()
Input optional
If you want to treat a value as optional you can use v.optional()
rule:
v.alpha().validate('') # false input required
v.alpha().validate(None) # false input required
v.optional(v.alpha()).validate('') # true
v.optional(v.alpha()).validate(None) # true
By optional we consider None
or an empty string (''
) as valid and don't pull input to rule inside.
See more on Optional.
Negating rules
You can use v.Not()
(IMPORTANT to type with upper N) to negate any rule:
Validator reuse
Once created, you can reuse your validator anywhere. Remember username_validator
?
username_validator.validate('respect'); //true
username_validator.validate('alexandre gaigalas'); // false
username_validator.validate('#$%'); //false
Exception types
Exception
:- All exceptions implement this interface;
ValidationException
:- Implements the
Exception
interface - Raise when the
check()
fails - All validation exceptions extend this class
- Available methods:
get_message()
;update_mode(mode)
;update_template(template)
;
NestedValidationException
:- Extends the
ValidationException
class - Usually thrown when the
claim()
fails - Available methods:
get_full_message()
;get_messages()
;
Informative exceptions
When something goes wrong, Validation can tell you exactly what's going on. For this,
we use the claim()
method instead of validate()
:
from respect_validation.Exceptions import NestedValidationException
try:
username_validator.claim('really messed up screen#name');
except NestedValidationException as exception:
print(exception.get_full_message())
The printed message is exactly this, as a nested Markdown list:
- All of the required rules must pass for "really messed up screen#name"
- "really messed up screen#name" must contain only letters (a-z) and digits (0-9)
- "really messed up screen#name" must not contain whitespace
- "really messed up screen#name" must have a length between 1 and 15
Getting all messages as a dict
If you want to get all the messages as a dict you can use get_messages()
for
that. The get_messages()
method returns an array with all the messages.
try:
username_validator.claim('really messed up screen#name');
except NestedValidationException as exception:
print(exception.get_messages())
The get_messages()
returns an array in which the keys are the name (better say ID) of the
validators, or its reference in case you are using Key or
Attribute rule:
{
'alnum': ['"really messed up screen#name" must contain only letters (a-z) and digits (0-9)'],
'noWhitespace': ['"really messed up screen#name" must not contain whitespace'],
'length': ['"really messed up screen#name" must have a length between 1 and 15']
}
Custom messages
Getting messages as a dict is fine, but sometimes you need to customize them
in order to present them to the user. This is possible using the get_messages()
method as well by passing the templates as an argument:
try:
username_validator.claim('really messed up screen#name')
except NestedValidationException as exception:
print(exception.get_messages({
'alnum': '{name} must contain only letters and digits',
'noWhitespace': '{name} cannot contain spaces',
'length': '{name} must not have more than 15 chars',
})
)
For all messages, the {name}
variable is available for templates. If you do
not define a name it uses the input to replace this placeholder.
The result of the code above will be:
{
'alnum': ['{name} must contain only letters and digits'],
'noWhitespace': ['{name} cannot contain spaces'],
'length': ['{name} must not have more than 15 chars']
}
Note that get_message()
will only return a message when the specific validation
in the chain fails.
Hint
Also, you can use Translation to change any output messages.
Validator name
On v.attribute()
and v.key()
, {name}
is the attribute/key name. For others,
is the same as the input. You can customize a validator name using:
Validation methods
We've seen validate()
that returns True or False and claim()
that raises a complete
validation report. There is also check()
method that returns an Exception
only with the first error found:
from respect_validation.Exceptions import ValidationException
try:
username_validator.check('really messed up screen#name')
except ValidationException as exception:
print(exception.get_message())
Message: