python - AttributeError:'bool'对象在检查数据库中是否存在某些东西时没有属性'_sa_instance_state'
问题描述
我是 Flask/SQLA 的新手,我正在创建一个小型学习应用程序,用户可以在其中查看美国国家公园(使用 National Park Service API)。我想允许登录的用户将公园保存到他们的收藏夹列表中以便以后查看。
parks 表开始为空,因为我们只是从 API 获取信息。如果用户将公园添加到他们的收藏夹中,我们将检查该特定公园是否在数据库中。如果没有,我们添加它。只有两列:一个自动递增的 ID 和一个公园代码。我使用的 API 为每个公园分配了一个四字母代码。例如优胜美地国家公园就是“yose”。
当我尝试将公园添加为我的最爱时,我得到AttributeError: 'bool' object has no attribute '_sa_instance_state'
. 这是处理将公园添加到收藏夹的路线:
@app.route("/<username>/add-favorite/<park_code>", methods=['POST'])
def add_favorites(username, park_code):
"""Add park to favorites"""
if "username" not in session or username != session['username']:
flash("You must be logged in to access this page")
return redirect("/login")
user = User.query.filter_by(username=username).first()
favorited_park = Park.query.filter_by(park_code=park_code) is not None
# if park already in the DB
if favorited_park:
**user.parks.append(favorited_park)**
db.session.commit()
flash("Existing park has been added to favorites")
return redirect("/<username>/favorite-parks")
# if the park is not already in the DB
else:
park = Park(park_code=park_code)
**user.parks.append(favorited_park)**
db.session.commit()
flash("Favorite park has been added")
return redirect("/<username>/favorite-parks")
上面引发错误的行是user.parks.append(favorited_park)
.
这是models.py
class User(db.Model):
"""User"""
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(20), unique=True, nullable=False)
password = db.Column(db.Text, nullable=False)
parks = db.relationship("Park", secondary="users_parks", backref="user")
class Park(db.Model):
"""Park"""
__tablename__ = "parks"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
park_code = db.Column(db.String(4), unique=True, nullable=False)
users = db.relationship("User", secondary="users_parks", backref="favorite_parks")
class UserPark(db.Model):
"""Mapping of a user to a park"""
__tablename__ = "users_parks"
user_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True)
park_id = db.Column(db.Integer, db.ForeignKey("parks.id"), primary_key=True)
def connect_db(app):
"""Connect to database."""
db.app = app
db.init_app(app)
我将不胜感激任何克服此错误的指针。
解决方案
favorited_park = Park.query.filter_by(park_code=park_code) is not None
我将分两部分演示该声明,首先:
Park.query.filter_by(park_code=park_code)
这将返回一个<class 'flask_sqlalchemy.BaseQuery'>
. 即,尚未执行的查询。要实际执行查询,您需要调用执行方法(请参阅此处),或遍历查询实例。
我要说的关键点是,在该语句的上下文中,这部分的结果是 never None
,并且始终是一个查询实例。
然后在该语句的第二部分(以及一些伪代码)的上下文中考虑:
favorited_park = <class 'flask_sqlalchemy.BaseQuery'> is not None
一些从未None
针对它是否不是进行测试的东西None
总是会返回True
。
这与以下内容相同:
1 is not None # True
"a string" is not None # True
object() is not None # True
所以,这条线本质上是这样的:
favorited_park = True
继续,这一行:
if favorited_park:
按原样评估真favorited_park
值True
,因此执行进入受保护的代码块。然后这一行:
user.parks.append(favorited_park)
是抛出错误的地方,因为 sqlalchemy 不允许您将布尔值附加到检测的集合。
要更正错误,您需要在查询中调用其中一种执行方法以返回Park
or的实例None
。一种选择可能是Query.one_or_none()
,来自文档:
如果查询未选择任何行,则返回 None。如果返回多个对象标识,或者为仅返回标量值而不是完整标识映射实体的查询返回多行,则引发 sqlalchemy.orm.exc.MultipleResultsFound。
所以那行可能变成:
favorited_park = Park.query.filter_by(park_code=park_code).one_or_none()
推荐阅读
- android - 为什么线性布局 maxHeight 不起作用?
- azure-functions - Azue Function V2 - 事件中心触发器不尊重主机配置 maxBatchSize
- kubernetes - 通过 kubernetes 注释进行 Traefik 健康检查
- logging - Logback:是否可以将 TimeBasedRollingPolicy 与 SizeBasedTriggeringPolicy 结合使用?
- java - RadioGroup 中的 RecyclerView 和 RadioButton
- javascript - 如何从 ajax 获取数据 - JS & Jquery
- powershell - 在 PowerShell 中比较多个 CSV 列并从两者返回完整数据
- python - Python / Pandas 中的 R 向量语法
- c++ - 将多个参数传递给 operator[]
- ruby-on-rails - Ruby On Rails - 重定向整个请求