繁体   English   中英

AttributeError:'bool' object 在检查数据库中是否存在某些东西时没有属性'_sa_instance_state'

[英]AttributeError: 'bool' object has no attribute '_sa_instance_state' when checking if something exists in the DB

我是 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'>的实例。 即,尚未执行的查询。 要实际执行查询,您需要调用执行方法(请参阅此处),或遍历查询实例。

我要说的关键点是,在该语句的上下文中,这部分的结果永远不是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:

评估truthy,因为favorited_park rk 是True ,所以执行进入那个受保护的代码块。 然后这一行:

user.parks.append(favorited_park)

是在哪里引发错误,因为 sqlalchemy 不允许您将 append 的 boolean 值添加到检测的集合。

要更正错误,您需要在查询中调用其中一种执行方法以返回ParkNone的实例。 一种选择可能是Query.one_or_none() ,来自文档:

如果查询未选择任何行,则返回 None。 如果返回多个 object 标识,或者如果为仅返回相对实体的查询返回多行标量值,则引发 sqlalchemy.orm.exc.MultipleResultsFound

所以那行可能变成:

favorited_park = Park.query.filter_by(park_code=park_code).one_or_none()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM