当我处理登录时,我无法使用 UserMixin 的 get_id() 方法传递 user_id 。 如果不调用 User 类的另一个实例,我就无法调用 MongoDB 创建的默认 ID。 这是我的模型.py
class User(UserMixin):
def __init__(self, email, username, password):
self.email = email
self.username = username
self.password = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
# datetime.now(tz=None) // gives local time
self.created_at = datetime.now(UTC)
def to_dict(self):
return {
'email': self.email,
'username': self.username,
'password': self.password.decode(),
'created_at': self.created_at
}
def save(self):
user_data = self.to_dict()
result = collection_users.insert_one(user_data)
return result.inserted_id
@classmethod
def from_dict(cls, data):
user = cls(data['email'], data['username'], data['password'])
if 'created_at' in data:
user.created_at = data['created_at']
return user
@classmethod
def find_by_username(cls, username):
user_data = collection_users.find_one({'username': username})
if user_data:
return user_data
return None
@classmethod
def find_by_email(cls, email):
email_data = collection_users.find_one({'email': email})
if email_data:
return email_data
return None
def check_password(self, password):
try:
# Note: The stored password is already in bytes, so no need to encode it
return bcrypt.checkpw(password, self.password)
except Exception as e:
# Handle exceptions (e.g., invalid hashing format, incorrect input)
print(f"Error checking password: {e}")
return False
def is_authenticated(self):
return self.is_active
def is_active(self):
return True
def is_anonymous(self):
return False
# Problem occurs in here
def get_id(self):
return str(self.to_dict().get('_id'))
我尝试过一些方法,例如在 get_id() 方法中使用用户名而不是 ID,但它也不起作用。
这也是我的routes.py,我评论了我的尝试及其输出。
@auth.route('/login', methods=['GET', 'POST'])
def login():
form = SignInForm()
if request.method == 'POST' and form.validate_on_submit():
username = form.username.data
password = form.password.data
found_user = User.find_by_username(username)
# [4]// user_id = str(found_user.get('_id'))
# [5]// user_id = found_user.get('_id')
user_id = found_user.get('_id')
try:
if found_user and bcrypt.checkpw(password.encode(), found_user['password'].encode()):
log_user = User(found_user["email"], found_user['username'], found_user["password"])
# -------------- FAILURE LOG ----------------
# [2]// login_user(log_user.get_id(), form.remember_me.data)
# [2]!> UserMixin,get_id() takes 1 positional arguments but two were given.
# [3]// login_user(log_user, form.remember_me.data)
# [3]!> No `id` attribute - override `get_id`
# [4]// login_user(user_id, form.remember_me.data)
# [4]!> 'str' object has no attribute 'is_active'
# [5]// login_user(user_id, form.remember_me.data)
# [5]!> 'ObjectId' object has no attribute 'is_active'
# [6]
# setattr(log_user, 'is_authenticated', True)
# setattr(log_user, 'is_active', True)
# setattr(log_user, 'is_anonymous', False)
# setattr(log_user, 'get_id', lambda: str(found_user.get('_id')))
# property 'is_authenticated' of 'User' object has no setter
# -------------------------------------------
login_user(log_user, form.remember_me.data)
flash(f'Welcome {found_user["username"]}', 'SUCCESS')
return redirect(url_for('auth.protected'))
except Exception as e:
flash(f'Error during login: {str(e)}', 'danger')
return redirect(url_for('auth.login'))
return render_template('auth/login.html', title='Sign In', form=form)
据我了解,我无法将正确的输入传递给 get_id() 方法,但此时我很困难。我看不到什么?
在
UserMixin
类中,它只提供默认方法,不提供属性,因此必须在 User 类中使用属性声明。
from mongoengine import *
class User(UserMixin, Document):
email = StringField()
username = StringField()
password = StringField()
created_at = DateTimeField()
def __init__(self, email, username, password):
self.email = email
self.username = username
self.password = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
self.created_at = datetime.now(UTC)
def to_dict(self):
return {
'id': str(self.pk),
'email': self.email,
'username': self.username,
'password': self.password.decode(),
'created_at': self.created_at
}
我建议你使用
mongoengine
来实现模型