<<深入理解Flask>>中遇到的那些坑
2017-02-05 12:16
736 查看
这篇文章的主要目的是分享学习<<深入理解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装饰器进行了装饰,因此访问这个页面要求有登陆信息:
进一步查看装饰器的实现:
错误提示说没有'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的关键,进一步看这个函数是在何时设置的:
前面使用sqlalchemy时曾在extensions.py中设置过这个函数:
可以看到,当时使用的是sqlite,因此这样返回的就是User对象,而现在使用mongodb后,这样返回的只是一个'BaseQuerySet',因此
出现了问题。
修改成下面后,问题解决:
问题的根本原因使用mongodb后,所有使用相关数据库操作的代码都要去适配。
坑一:
在把博客从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_required def 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_loader def load_user(userid): from .models import User return User.objects(id=userid)
可以看到,当时使用的是sqlite,因此这样返回的就是User对象,而现在使用mongodb后,这样返回的只是一个'BaseQuerySet',因此
出现了问题。
修改成下面后,问题解决:
@login_manager.user_loader def load_user(userid): from .models import User return User.objects(id=userid).first()
问题的根本原因使用mongodb后,所有使用相关数据库操作的代码都要去适配。
相关文章推荐
- <<深入理解计算机系统>>之构建tinyweb源码
- <<深入理解mariadb和mysql>>之mysql执行计划分析学习记录
- <<深入理解mariadb和mysql>>之mysql优化学习记录
- &lt;&lt;深入理解计算机系统&gt;&gt;家庭作业3.38, 分析全过程
- c语言深入理解<2>
- <深入理解JavaScript>学习笔记(2)_揭秘命名函数表达式
- <深入理解计算机系统> 通过程序的机器级表示来理解函数栈
- c语言深入理解<4>
- 怎样来理解<全局变量>与<局部变量>
- <<深入理解java内存模型>>学习总结
- 自定义组件<六>:深入理解ViewGroup
- <<C++ design patterns and Derivatives Pricing>> 学习系列 CH1-对蒙特卡洛基本理解
- 深入理解软件包的配置、编译与安装 <转>
- 深入理解WeakHashmap<转>
- <<C++ Primer>>中文版 重载箭头运算符的理解
- <深入理解计算机系统>笔记
- <<深入理解linux内核>>读书笔记 (一): 内存寻址
- <深入理解JavaScript>学习笔记(1)_编写高质量JavaScript代码的基本要点
- <深入理解计算机系统> CSAPP Tiny web 服务器
- 从显示行号之功能->理解<ui:repeat>与<c:forEach>