Validators¶
Introduction¶
As Reforms expands Pydantic, then you can use all existed features including validators. Here you can see a simple example, for more information please go to the appropriate page of the pydantic documentation.
from pydantic import BaseModel, ValidationError, validator
from reforms import BooleanField, StringField
class UserModel(BaseModel):
name: StringField()
is_admin: BooleanField()
username: StringField()
password1: StringField()
password2: StringField()
@validator("name")
def name_must_contain_space(cls, v):
if " " not in v:
raise ValueError("must contain a space")
return v.title()
@validator("password2")
def passwords_match(cls, v, values):
if "password1" in values and v != values["password1"]:
raise ValueError("passwords do not match")
return v
@validator("username")
def username_alphanumeric(cls, v):
assert v.isalnum(), "must be alphanumeric"
return v
@validator("is_admin")
def contains_admin_name(cls, v, values):
if v and ("name" not in values or "admin" not in values["name"].lower()):
raise ValueError('if user is admin, his name must contain "admin" part')
return v
user = UserModel(
name="samuel colvin admin",
username="scolvin",
password1="zxcvbn",
password2="zxcvbn",
is_admin=True,
)
print(user)
try:
UserModel(
name="samuel",
username="scolvin",
password1="zxcvbn",
password2="zxcvbn2",
is_admin=True,
)
except ValidationError as e:
print(e)
Built-in validators¶
If you used wtforms before, you have definitely used their built-in validators and implemented yours owns in cases, when you needed some custom behavior. Reforms also contains a similar validators list. Here is a simple example.
from pydantic import BaseModel, ValidationError
from reforms import StringField
from reforms.validators import Length
class ContactUsModel(BaseModel):
name: StringField(validators=[Length(min=5)])
message: StringField()
contact = ContactUsModel(name="Roman", message="Some message")
print(contact)
try:
ContactUsModel(
message="Temp",
)
except ValidationError as e:
print(e)
try:
ContactUsModel(
name="Dan",
)
except ValidationError as e:
print(e)
All current built-in validators you can see below.
Length
¶
- validates the length of a string.
min: int =- 1
: The minimum required length of the string. If not provided, minimum length will not be checked.max: int =- 1
: The maximum length of the string. If not provided, maximum length will not be checked.message: str = ""
: Error message to raise in case of a validation error. Can be interpolated using {min} and {max} if desired. Useful defaults are provided depending on the existence of min and max.
AnyOf
¶
- compares the incoming data to a sequence of valid inputs.
values: Sequence[Any]
: A sequence of valid inputs.message: str = "Invalid value, must be one of: {values}."
: Error message to raise in case of a validation error. {values} contains the list of values.values_formatter: Callable = None
: Function used to format the list of values in the error message.
NoneOf
¶
- compares the incoming data to a sequence of invalid inputs.
values: Sequence[Any]
: A sequence of valid inputs.message: str = "Invalid value, must be one of: {values}."
: Error message to raise in case of a validation error. {values} contains the list of values.values_formatter: Callable = None
: Function used to format the list of values in the error message.
Write your custom validator¶
To write custom validator, you need to create a callable object (function or class
with implemented __call__
method) with the parameters below.
Warning
Validators should either return the parsed value or raise a ValueError
,
TypeError
, or AssertionError
(assert
statements may be used). It's the
same as with default pydantic validators.
Parameter | Type | Description |
---|---|---|
value | Any | Current field value |
field (Optional) | ModelField | Parameter to get access to the field itself |
from typing import Callable
from pydantic import BaseModel, ValidationError
from reforms import StringField
def has_lines(n: int = 2) -> Callable:
def _has_lines(value: str):
if len(value.split("\n")) < n:
raise ValueError(f"Value doesn't contain minimum {n} lines")
return value
return _has_lines
class MessageModel(BaseModel):
content: StringField(validators=[has_lines(n=3)])
contact = MessageModel(
content="""
First sentence.
Second sentence.
Third sentence"""
)
print(contact)
try:
MessageModel(content="One line")
except ValidationError as e:
print(e)