如何使用MongoDB结构处理flask登录?

问题描述 投票:0回答:1

当我处理登录时,我无法使用 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() 方法,但此时我很困难。我看不到什么?

mongodb flask flask-login
1个回答
0
投票

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
来实现模型

© www.soinside.com 2019 - 2024. All rights reserved.