WTForms 是一个 Python 库,用于处理和验证 Web 表单。它提供了很多功能来简化表单处理,包括字段类型、验证器、错误消息等。在 WTForms 中,validate
机制是用于确保表单数据满足特定条件的关键部分。
1.验证器(Validators)
WTForms 提供了多种内置的验证器,如 DataRequired
, Length
, Email
, EqualTo
等,这些可以被添加到表单字段上以执行特定的验证规则。例如:
python
from wtforms import StringField, validators
class LoginForm(Form):
username = StringField('Username', [validators.DataRequired()])
password = PasswordField('Password', [
validators.DataRequired(),
validators.Length(min=8)
])
在这个例子中,DataRequired
确保字段不为空,Length
则确保密码长度至少为 8。
2.自定义验证器
你也可以定义自己的验证函数,并将其作为验证器使用。这个函数应该接收表单实例和字段实例作为参数,并在验证失败时抛出 ValidationError
异常。例如:
python
from wtforms import StringField, ValidationError
from wtforms.validators import StopValidation
def unique_username(form, field):
if User.query.filter_by(username=field.data).first():
raise ValidationError('Username already exists.')
class RegistrationForm(Form):
username = StringField('Username', [unique_username])
在这个例子中,unique_username
函数检查数据库中是否已存在相同的用户名,如果存在,则抛出 ValidationError
。
3.全局验证
除了字段级别的验证之外,你还可以定义全局验证方法,在表单类中定义以 validate_
开头的方法,后面跟着字段名,这会触发对整个表单的验证。这种方法通常用于需要跨多个字段的复杂验证逻辑。例如:
python
class RegistrationForm(Form):
username = StringField('Username')
password = PasswordField('Password')
confirm_password = PasswordField('Confirm Password')
def validate_confirm_password(self, field):
if field.data != self.password.data:
raise ValidationError('Passwords do not match.')
这里,validate_confirm_password
方法确保用户输入的密码与其确认密码相同。
4. 使用多个验证器
你可以将多个验证器应用于同一个字段,例如,确保电子邮件格式正确并且非空:
python
from wtforms import StringField, EmailField
from wtforms.validators import DataRequired, Email
class ContactForm(Form):
email = EmailField('Email', validators=[DataRequired(), Email()])
5. 自定义验证器示例 - 检查年龄
假设你想要验证用户年龄必须大于18岁:
python
from datetime import date
def is_adult(form, field):
today = date.today()
age = today.year - field.data.year - ((today.month, today.day) < (field.data.month, field.data.day))
if age < 18:
raise ValidationError('You must be at least 18 years old.')
class RegistrationForm(Form):
birth_date = DateField('Birth Date', validators=[is_adult])
6. 验证唯一性 - 检查用户名或邮箱是否已被注册
在数据库中检查某个值是否唯一:
python
from myapp.models import User
def unique_username(form, field):
if User.query.filter_by(username=field.data).first() is not None:
raise ValidationError('Username already exists.')
def unique_email(form, field):
if User.query.filter_by(email=field.data).first() is not None:
raise ValidationError('Email already exists.')
class RegistrationForm(Form):
username = StringField('Username', validators=[unique_username])
email = StringField('Email', validators=[unique_email])
7. 自定义错误消息
你可以覆盖默认的错误消息,使其更加友好或具体:
python
class ContactForm(Form):
subject = StringField('Subject', validators=[DataRequired(message='Please enter a subject.')])
message = TextAreaField('Message', validators=[Length(max=200, message='Your message is too long.')])
下面是一个使用 验证器的用户注册完整例子:
python
from wtforms import Form, StringField, PasswordField, validators
class RegistrationForm(Form):
username = StringField('Username', [validators.Length(min=4, max=25)])
email = StringField('Email Address', [validators.Length(min=6, max=35),
validators.Email()])
password = PasswordField('New Password', [
validators.DataRequired(),
validators.EqualTo('confirm', message='Passwords must match')
])
confirm = PasswordField('Repeat Password')
# 使用表单
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate():
# 如果表单验证成功,可以进一步处理数据,比如保存到数据库
user = User(username=form.username.data, email=form.email.data,
password=generate_password_hash(form.password.data))
db.session.add(user)
db.session.commit()
else:
# 如果表单验证失败,显示错误消息
flash_errors(form)
在这个例子中,RegistrationForm
包含了 username
, email
, password
, 和 confirm
字段。password
字段使用了 EqualTo
验证器,它会检查 password
和 confirm
字段的值是否相同。如果这两个字段的值不同,EqualTo
验证器会抛出一个 ValidationError
,并附带错误消息 "Passwords must match"。
EqualTo
验证器的第一个参数是要与当前字段比较的另一个字段的名称。在上面的例子中,password
字段通过 EqualTo('confirm')
与 confirm
字段进行比较。
如果在实际应用中遇到问题,或者需要进一步定制验证逻辑,你也可以自定义验证函数来配合 EqualTo
或其他验证器一起使用。