【问题标题】:AttributeError: 'dict' object has no attribute 'is_active' (PyMongo And Flask)AttributeError:“dict”对象没有属性“is_active”(PyMongo 和 Flask)
【发布时间】:2018-11-20 21:40:44
【问题描述】:
@app.route("/register", methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        users = mongo.db.users
        hash_password=bcrypt.generate_password_hash(form.password.data).decode('utf-8')
        eml=form.email.data
        gen=form.gender.data
        ctry=form.country.data
        profile={'name' : form.username.data, 'password' :hash_password,'email':eml,'gender':gen,'country':ctry}
        users.insert(profile)
        #users.insert({'name' : form.username.data, 'password' :form.password.data})
        flash(f'Your has been Account created for Username {form.username.data}!, You can login', 'success')
        return redirect(url_for('login'))
        #return redirect(url_for('home'))
    return render_template('register.html', title='Register', form=form)

@app.route("/login", methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        users = mongo.db.users
        loginuser = users.find_one({'email' : form.email.data})
        if loginuser and bcrypt.check_password_hash(loginuser['password'],form.password.data):
        #if form.email.data == 'admin@blog.com' and form.password.data == 'password':
            login_user(loginuser,remember=form.data.remember)
            return redirect(url_for('home'))
            #flash('You have been logged in!', 'success')
            #return redirect(url_for('home'))
        else:
            flash('Login Unsuccessful. Please check username and password', 'danger')
    return render_template('login.html', title='Login', form=form)

我已经创建了一个简单的注册和登录方法,使用烧瓶和 pymongo 的组合。 现在对于用户会话管理,我正在使用 flask_login 但它给了我这个错误 AttributeError: 'dict' 对象没有属性 'is_active'

我发现不同帖子的解决方案是在 UserClass 中添加 UserMaxIn 但我没有任何用户模型类,我也不想这样做

这个错误的解决方法是什么?

【问题讨论】:

    标签: python flask pymongo flask-login


    【解决方案1】:

    Flask-Login 要求您使用类来表示用户,而不是原始字典。

    documentation 中所述,该类需要实现一些属性和方法,包括is_active() 方法。

    UserMixin 类是为所有必需的属性和方法提供默认实现的基类,您可以扩展它并创建一个简单的 User 类。


    更新:添加示例

    根据你已经拥有的,你能做的最简单的事情是:

    • 创建自定义User 类,扩展UserMixin
    • 将来自 MongoDB 的 json 对象存储在 User 类中
    • 覆盖您需要不同于默认行为的方法
    • /login 路由中创建User 类的实例并将其传递给flask_login.login_user()

    用户类

    class User(UserMixin):
        def __init__(self, user_json):
            self.user_json = user_json
    
        # Overriding get_id is required if you don't have the id property
        # Check the source code for UserMixin for details
        def get_id(self):
            object_id = self.user_json.get('_id')
            return str(object_id)
    

    对于所有方法/属性(is_authenticatedis_activeis_anonymous),除了get_id,它使用默认实现。如果您不需要默认实现,则无需扩展UserMixin,但您必须自己实现所有方法。

    登录路由中User类的使用

    @app.route("/login", methods=['GET', 'POST'])
    def login():
        form = LoginForm()
        if form.validate_on_submit():
            users = mongo.db.users
            loginuser_json = users.find_one({'email': form.email.data})
            if loginuser_json and bcrypt.check_password_hash(loginuser_json['password'], form.password.data):
                # Create a custom user and pass it to login_user:
                loginuser = User(loginuser_json)
                login_user(loginuser, remember=form.data.remember)
                return redirect(url_for('home'))
            else:
                flash('Login Unsuccessful. Please check username and password', 'danger')
        return render_template('login.html', title='Login', form=form)
    

    请记住,您还必须提供user_loader,如here 所述。例如,给定 user_id,在 MongoDB 上执行查询并返回 User 对象:

    @login_manager.user_loader
    def load_user(user_id):
        users = mongo.db.users
        user_json = users.find_one({'_id': ObjectId(user_id)})
        return User(user_json)
    

    有用的链接

    【讨论】:

    • 你能给我一个简单的代码来创建用户类吗?以及如何在登录路径中调用该类
    • 非常感谢,它的工作原理如何获取当前用户的电子邮件?
    • 可以从json对象中获取:loginuser_json.get('email')。如果您想从User 对象中获取它:user_object.user_json.get('email'),或者您可以在User 类中添加一个新方法get_email
    • def get_mail(self): object_id = self.user_json.get('email') return str(object_id) 这样?
    • 是的,它可以工作,但电子邮件已经是字符串,所以你可以简单地:def get_mail(self): return self.user_json.get('email')
    猜你喜欢
    • 2014-12-23
    • 2016-07-22
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    • 2018-09-02
    • 2021-01-30
    • 2020-09-11
    相关资源
    最近更新 更多