Flask WTForms 自定义验证器不工作

Flask WTForms custom validators not working

所以我试图在我的 Flask 应用程序中实现自定义验证器,但我 运行 遇到了问题。我为 RegisterForm 编写的自定义验证器 UniqueRequired() 似乎可以正常工作,但我的 LoginForm 验证器似乎根本没有被调用,ValidUsername() 中的打印语句没有打印。我已经尝试将验证器放在同一个文件中,在不同的语句中导入它们,并更改验证器的顺序,但没有任何效果。

这是我的 forms.py 文件:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Length, EqualTo
from validators import UniqueRequired, VaildUsername, ValidPassword

class LoginForm(FlaskForm):
    username = StringField("Username:", validators=[DataRequired(), VaildUsername], id="username")
    password = PasswordField("Password:", validators=[DataRequired(), ValidPassword], id="password")

class RegisterForm(FlaskForm):
    username = StringField("Username:", validators=[DataRequired(), UniqueRequired, Length(min=5, max=25)], id="username")
    password = PasswordField("Password:", validators=[DataRequired(), Length(min=8)], id="password")
    confirmpassword = PasswordField("Confirm Password:", validators=[DataRequired(), EqualTo('password', message="Passwords don't match")], id="conpassword")

我的 validators.py 文件:

def UniqueRequired(form, field):
    otheruser = User.query.filter_by(username=field.data).first()
    if otheruser:
        raise ValidationError("Username Taken")

def VaildUsername(form, field):
    user = User.query.filter_by(username=field.data).first()
    print(user)
    if not user:
        raise ValidationError("Invalid Username")

def ValidPassword(form, field):
    user = User.query.filter_by(username=form.username.data).first()
    if not check_password_hash(user.password, field.data):
        raise ValidationError("Incorrect Password")

和我的 /login 和 /register 路由:

@app.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm()
    if form.validate_on_submit:
        print("Form Valid")
    return render_template("login.html", form=form)

@app.route("/register", methods=["GET", "POST"])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        print("Form Valid")
    return render_template("register.html", form=form)

我能想到 2 种可能的解决方案
首先:我认为在验证器列表中自定义验证器之后应该有一组括号。

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Length, EqualTo
from validators import UniqueRequired, VaildUsername, ValidPassword

class LoginForm(FlaskForm):
    username = StringField("Username:", validators=[DataRequired(), VaildUsername()], id="username")
    password = PasswordField("Password:", validators=[DataRequired(), ValidPassword()], id="password")

class RegisterForm(FlaskForm):
    username = StringField("Username:", validators=[DataRequired(), UniqueRequired(), Length(min=5, max=25)], id="username")
    password = PasswordField("Password:", validators=[DataRequired(), Length(min=8)], id="password")
    confirmpassword = PasswordField("Confirm Password:", validators=[DataRequired(), EqualTo('password', message="Passwords don't match")], id="conpassword")

其次:您可以为表单Class中的每个class成员创建一个单独的方法Class。
调用 validate_on_submit 时会自动调用它们。
你可以这样做

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Length, EqualTo

class LoginForm(FlaskForm):
    username = StringField("Username:", validators=[DataRequired()], id="username")
    password = PasswordField("Password:", validators=[DataRequired(), ValidPassword], id="password")
 # validate_<fieldname>  method will automatically validate
    def validate_username(self,field):
    user = User.query.filter_by(username=field.data).first()
    # print(user)
    if not user:
        raise ValidationError("Invalid Username")

    class RegisterForm(FlaskForm):
        username = StringField("Username:", validators=[DataRequired(), UniqueRequired, Length(min=5, max=25)], id="username")
        password = PasswordField("Password:", validators=[DataRequired(), Length(min=8)], id="password")
        confirmpassword = PasswordField("Confirm Password:", validators=[DataRequired(), EqualTo('password', message="Passwords don't match")], id="conpassword")

如您所见,我已经给出了 LoginForm 中仅用户名字段的示例,您也可以对其他字段执行类似操作。

好的,我一直在摸索,我发现了问题。在我的 /login 路由中,我使用了 form.validate_on_submit,但我没有放入任何括号。更正后的代码如下所示:

@app.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        print("Form Valid")
    return render_template("login.html", form=form)

@app.route("/register", methods=["GET", "POST"])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        print("Form Valid")
    return render_template("register.html", form=form)