Flask登录报错:TypeError: LoginForm.validate()意外收到extra_validators参数
Flask+MongoDB登录报错:TypeError: LoginForm.validate() got an unexpected keyword argument 'extra_validators'
问题场景
在使用Flask开发应用并结合MongoDB作为数据库时,登录环节触发以下错误:
TypeError: LoginForm.validate() got an unexpected keyword argument 'extra_validators'
应用代码(app.py)
from flask import Flask, render_template, request, redirect, url_for from flask_mongoengine import MongoEngine from flask_security import Security, MongoEngineUserDatastore, UserMixin, RoleMixin, login_required, login_user, logout_user, current_user, LoginForm app = Flask(__name__) app.config['DEBUG'] = True app.config['SECRET_KEY'] = 'super-secret-key' app.config['SECURITY_PASSWORD_SALT'] = 'super-secret-salt' app.config['MONGODB_SETTINGS'] = { 'db': 'flask-login', 'host': 'localhost', 'port': 27017, } db = MongoEngine(app) class Role(db.Document, RoleMixin): name = db.StringField(max_length=80) description = db.StringField(max_length=255) class User(db.Document, UserMixin): name = db.StringField(max_length=255) email = db.StringField(max_length=255, unique=True) password = db.StringField(max_length=255) active = db.BooleanField(default=True) confirmed_at = db.DateTimeField() roles = db.ListField(db.ReferenceField(Role), default=[]) user_datastore = MongoEngineUserDatastore(db, User, Role) security = Security(app, user_datastore) @app.route('/dashboard') @login_required def dashboard(): return render_template('dashboard.html') @app.route('/') def home(): return render_template('home.html') @app.route('/register', methods=['POST']) def add_user(): name = request.form['name'] email = request.form['email'] password = request.form['password'] user = User(name=name, email=email, password=password) user.save() return redirect('/') @app.route('/logout') @login_required def logout(): logout_user() return redirect('/')
临时解决方案(不推荐)
通过修改flask_wtf包中form.py的validate_on_submit函数,删除extra_validators=None参数,可暂时解决问题:
修改前代码
def validate_on_submit(self, extra_validators=None): """Call :meth:`validate` only if the form is submitted. This is a shortcut for ``form.is_submitted() and form.validate()``. """ return self.is_submitted() and self.validate(extra_validators=extra_validators)
修改后代码
def validate_on_submit(self): """Call :meth:`validate` only if the form is submitted. This is a shortcut for ``form.is_submitted() and form.validate()``. """ return self.is_submitted() and self.validate()
但修改第三方包源码会导致后续依赖更新时丢失修改,且破坏环境一致性,不建议采用。
正确解决方案
该错误源于flask-security的LoginForm与flask-wtf版本不兼容:新版flask-wtf的validate_on_submit会传递extra_validators参数,但旧版flask-security的LoginForm.validate()方法未定义该参数。以下是两种可行方案:
方案1:调整依赖版本
查看flask-security官方文档,匹配兼容的flask-wtf版本:
- 若使用
flask-security < 4.0,需搭配flask-wtf < 1.0; - 若升级
flask-security到4.0+版本,可兼容新版flask-wtf。
执行对应版本调整命令(以pip为例):
# 降级flask-wtf适配旧版flask-security pip install flask-wtf==0.14.3 # 或升级flask-security到兼容版本 pip install flask-security==4.1.5
方案2:自定义LoginForm覆盖validate方法
创建自定义LoginForm,重写validate方法以接受extra_validators参数,避免报错:
from flask_security.forms import LoginForm as BaseLoginForm class LoginForm(BaseLoginForm): def validate(self, extra_validators=None): # 调用父类validate方法,忽略extra_validators参数 return super().validate()
在初始化Security时指定自定义登录表单:
security = Security(app, user_datastore, login_form=LoginForm)
内容的提问来源于stack exchange,提问作者Levizoca
相关产品推荐
相关产品推荐

