1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
|
Validators
==========
Auto-assigned validators
------------------------
By default WTForms-Alchemy ModelForm assigns the following validators:
* InputRequired validator if column is not nullable and has no default value
* DataRequired validator if column is not nullable, has no default value and is of type `sqlalchemy.types.String`
* NumberRange validator if column if of type Integer, Float or Decimal and column info parameter has min or max arguments defined
* DateRange validator if column is of type Date or DateTime and column info parameter has min or max arguments defined
* TimeRange validator if column is of type Time and info parameter has min or max arguments defined
* Unique validator if column has a unique index
* Length validator for String/Unicode columns with max length
* Optional validator for all nullable columns
Unique validator
----------------
WTForms-Alchemy automatically assigns unique validators for columns which have unique indexes defined. Unique validator raises ValidationError exception whenever a non-unique value for given column is assigned. Consider the following model/form definition. Notice how you need to define get_session() classmethod for your form. Unique validator uses this method for getting the appropriate SQLAlchemy session.
::
engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(100), nullable=False)
email = sa.Column(
sa.Unicode(255),
nullable=False,
unique=True
)
class UserForm(ModelForm):
class Meta:
model = User
@classmethod
def get_session():
# this method should return sqlalchemy session
return session
Here UserForm would behave the same as the following form:
::
class UserForm(Form):
name = TextField('Name', validators=[DataRequired(), Length(max=100)])
email = TextField(
'Email',
validators=[
DataRequired(),
Length(max=255),
Unique(User.email, get_session=lambda: session)
]
)
If you are using Flask-SQLAlchemy or similar tool, which assigns session-bound query property to your declarative models, you don't need to define the get_session() method. Simply use:
::
Unique(User.email)
Using unique validator with existing objects
--------------------------------------------
When editing an existing object, WTForms-Alchemy must know the object currently edited to avoid raising a ValidationError. Here how to proceed to inform WTForms-Alchemy of this case.
Example::
obj = MyModel.query.get(1)
form = MyForm(obj=obj)
form.populate_obj(obj)
form.validate()
WTForms-Alchemy will then understand to avoid the unique validation of the object with this same object.
Range validators
----------------
WTForms-Alchemy automatically assigns range validators based on column type and assigned column info min and max attributes.
In the following example we create a form for Event model where start_time can't be set in the past.
::
class Event(Base):
__tablename__ = 'event'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
start_time = sa.Column(sa.DateTime, info={'min': datetime.now()})
class EventForm(ModelForm):
class Meta:
model = Event
Additional field validators
---------------------------
Example::
from wtforms.validators import Email
class User(Base):
__tablename__ = 'user'
name = sa.Column(sa.Unicode(100), primary_key=True, nullable=False)
email = sa.Column(
sa.Unicode(255),
nullable=False,
info={'validators': Email()}
)
class UserForm(ModelForm):
class Meta:
model = User
Now the 'email' field of UserForm would have Email validator.
Overriding default validators
-----------------------------
Sometimes you may want to override what class WTForms-Alchemy uses for email, number_range, length etc. validations.
For all automatically assigned validators WTForms-Alchemy provides configuration options to override the default validator.
In the following example we set a custom Email validator for User class.
::
from sqlalchemy_utils import EmailType
from wtforms_components import Email
class User(Base):
__tablename__ = 'user'
name = sa.Column(sa.Unicode(100), primary_key=True, nullable=False)
email = sa.Column(
EmailType,
nullable=False,
)
class MyEmailValidator(Email):
def __init__(self, message='My custom email error message'):
Email.__init__(self, message=message)
class UserForm(ModelForm):
class Meta:
model = User
email_validator = MyEmailValidator
If you don't wish to subclass you can simply use functions / lambdas:
::
def email():
return Email(message='My custom email error message')
class UserForm(ModelForm):
class Meta:
model = User
email_validator = email
You can also override validators that take multiple arguments this way:
::
def length(min=None, max=None):
return Length(min=min, max=max, message='Wrong length')
class UserForm(ModelForm):
class Meta:
model = User
length_validator = length
Here is the full list of configuration options you can use to override default validators:
* email_validator
* length_validator
* unique_validator
* number_range_validator
* date_range_validator
* time_range_validator
* optional_validator
Disabling validators
--------------------
You can disable certain validators by assigning them as `None`. Let's say you want to disable nullable columns having `Optional` validator. This can be achieved as follows::
class UserForm(ModelForm):
class Meta:
model = User
optional_validator = None
|