首页 > 学院 > 开发设计 > 正文

<<深入理解Flask>>中遇到的那些坑

2019-11-14 09:23:18
字体:
来源:转载
供稿:网友

这篇文章的主要目的是分享学习<<深入理解Flask>>这本书中遇到的坑,可以使遇到相同问题的同学少走弯路。大家有遇到或解决过相关问题的,也欢迎分享出来。

坑一:

在把博客从sqlite重构到mongodb时,在登陆成功后想要访问只有登陆用户才能访问的页面时,遇到了下面的错误:

in decorated_view    elif not current_user.is_authenticated:  File "/usr/local/lib/python3.4/dist-packages/werkzeug/local.py", line 343, in __getattr__    return getattr(self._get_current_object(), name)AttributeError: 'BaseQuerySet' object has no attribute 'is_authenticated'

我是在登陆成功后,准备写新的博客时遇到的这个错误。可以看到,这个函数用login_required装饰器进行了装饰,因此访问这个页面要求有登陆信息:

@blog_bluePRint.route('/new', methods=['GET', 'POST'])@login_requireddef new_post():    form = PostForm()    if form.validate_on_submit():       ......    return render_template('new.html', form=form)进一步查看装饰器的实现:
def login_required(func):      @wraps(func)    def decorated_view(*args, **kwargs):        if request.method in EXEMPT_METHODS:            return func(*args, **kwargs)        elif current_app.login_manager._login_disabled:            return func(*args, **kwargs)        elif not current_user.is_authenticated:            return current_app.login_manager.unauthorized()        return func(*args, **kwargs)    return decorated_view可以看到出错的语句就是在访问current_user.is_authenticated时报错的.

错误提示说没有'is_authenticated'属性,查看User的models定义:

class User(mongo.Document):   ...    def is_authenticated(self):        if isinstance(self, AnonymousUserMixin):            return False        else:            return True也是定义了这个属性的,再仔细看出错提示是说 'BaseQuerySet'没有这个属性,为什么会报这个类错误呢,我们的User应该不是这个类啊,因此查看'current_user'的具体实现:

current_user = LocalProxy(lambda: _get_user())一路跟踪,可以看出最终的user是在下面设置的:

flask_login/login_manager.py:

def reload_user(self, user=None):        ctx = _request_ctx_stack.top        if user is None:            user_id = session.get('user_id')            if user_id is None:                ctx.user = self.anonymous_user()            else:                if self.user_callback is None:                    raise Exception(                        "No user_loader has been installed for this "                        "LoginManager. Add one with the "                        "'LoginManager.user_loader' decorator.")                user = self.user_callback(user_id)...通过user_id获取user,而这个user_callback就是通过user_id获取user的关键,进一步看这个函数是在何时设置的:

def user_loader(self, callback):        '''        This sets the callback for reloading a user from the session. The        function you set should take a user ID (a ``unicode``) and return a        user object, or ``None`` if the user does not exist.        :param callback: The callback for retrieving a user object.        :type callback: callable        '''        self.user_callback = callback        return callback前面使用sqlalchemy时曾在extensions.py中设置过这个函数:
@login_manager.user_loaderdef load_user(userid):    from .models import User    return User.objects(id=userid)可以看到,当时使用的是sqlite,因此这样返回的就是User对象,而现在使用mongodb后,这样返回的只是一个'BaseQuerySet',因此出现了问题。修改成下面后,问题解决:
@login_manager.user_loaderdef load_user(userid):    from .models import User    return User.objects(id=userid).first()问题的根本原因使用mongodb后,所有使用相关数据库操作的代码都要去适配。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表