Flask Login中User.get_id()参数错误的解决方法咨询
修复Flask-Login TypeError及MongoDB适配方案
错误原因
你写的User类里,is_authenticated、is_active、is_anonymous、get_id这些实例方法都没加self参数。Python类的实例方法必须把self作为第一个参数,Flask-Login调用这些方法时会自动传入用户实例,所以才会触发TypeError: User.get_id() takes 0 positional arguments but 1 was given。
分步修复及MongoDB适配
1. 补全类方法的self参数
先把User类的方法补全self,同时完善get_id的返回值(得返回能唯一标识用户的字符串,比如邮箱或者MongoDB文档的_id):
class User(): def __init__(self, email, password, user_id=None): self.email = email self.password = password self.user_id = user_id # 后续存MongoDB返回的文档_id def is_authenticated(self): return True def is_active(self): return True def is_anonymous(self): return False # 正常登录用户不是匿名的,这里要修正 def get_id(self): # 返回唯一标识,优先用MongoDB的_id转字符串,没有就用邮箱 return str(self.user_id) if self.user_id else self.email
2. 用UserMixin简化代码(解决之前的Mixin问题)
之前用UserMixin出错,大概率是没正确继承。UserMixin已经帮你实现了那四个方法,直接继承就能省掉重复代码:
from flask_login import UserMixin class User(UserMixin): def __init__(self, email, password, user_id=None): self.email = email self.password = password self.id = user_id # UserMixin的get_id会自动返回self.id的字符串形式 # 不用再写is_authenticated这些方法,Mixin已经实现
3. 对接云端MongoDB的用户加载逻辑
你的load_user函数现在返回User.get(user_id),但User类根本没get方法,得改成从MongoDB查用户:
先在app.py里加MongoDB连接:
# 连接云端MongoDB client = MongoClient("你的云端MongoDB连接字符串") db = client["你的数据库名称"] users_collection = db["users"] # 假设用户数据存在users集合里
然后修改load_user和登录逻辑,从MongoDB验证用户:
from bson.objectid import ObjectId # 需要导入这个来处理MongoDB的_id @login_manager.user_loader def load_user(user_id): # 根据user_id从MongoDB查用户文档 user_doc = users_collection.find_one({"_id": ObjectId(user_id)}) if user_doc: # 把MongoDB文档转成User实例 return User( email=user_doc["email"], password=user_doc["password"], user_id=user_doc["_id"] ) return None @app.route("/login", methods=["GET", "POST"]) def login(): form = LoginForm() if form.validate_on_submit(): # 从MongoDB查输入的用户(注意:你表单用的是username,建议改成email统一字段) user_doc = users_collection.find_one({"email": form.username.data}) # 注意:实际项目绝对不能明文存密码!下面只是示例,要加密验证 if user_doc and user_doc["password"] == form.password.data: user = User( email=user_doc["email"], password=user_doc["password"], user_id=user_doc["_id"] ) login_user(user) return redirect(url_for("你的首页路由名")) # 登录成功跳首页 # 验证失败给提示 flash("用户名或密码错误") return render_template("header/login.html", form=form)
4. 关键注意事项
- 密码必须加密:明文存密码是严重安全问题,用
werkzeug.security的工具处理:from werkzeug.security import generate_password_hash, check_password_hash # 注册时存加密后的密码 hashed_pw = generate_password_hash("用户输入的密码") users_collection.insert_one({"email": "xxx@xxx.com", "password": hashed_pw}) # 登录时验证 if user_doc and check_password_hash(user_doc["password"], form.password.data): # 验证通过 - 表单字段统一:你的LoginForm用的是
username,但User类用的是email,建议把表单字段改成email,避免混淆。 - 删除重复代码:app.py里重复写了
login_manager.init_app(app),删掉其中一个就行。
内容的提问来源于stack exchange,提问作者Opeyemi Orioke
相关产品推荐
相关产品推荐

