AttributeError:“bool”对象在检查数据库中是否存在某些内容时没有属性“\u sa\u instance\u state”

2024-05-19 19:28:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Flask/SQLA新手,我正在创建一个小型学习应用程序,用户可以在其中查看美国国家公园(使用国家公园服务API)。我想允许登录用户将公园保存到他们的收藏夹列表中,以便以后查看

parks表开始为空,因为我们只是从API获取信息。如果用户将一个公园添加到他们的收藏夹中,我们将检查该公园是否在数据库中。如果没有,我们加上它。只有两列:一个自动递增的ID和一个公园代码。我使用的API为每个公园分配了一个四个字母的代码。例如,约塞米蒂国家公园就是“约塞米蒂”

当我尝试添加一个公园作为我的最爱时,我得到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)  

如果有人能给我指点克服这个错误,我将不胜感激


Tags: toidtrueappparkdbusernamecode
1条回答
网友
1楼 · 发布于 2024-05-19 19:28:37
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'>的实例。即,尚未执行的查询。要实际执行查询,需要调用一个执行方法(请参见here),或迭代查询实例

我要说的关键点是,在该语句的上下文中,这部分的结果永远不会是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_parkTrue,所以执行进入那个受保护的代码块。那么这一行:

user.parks.append(favorited_park)

是引发错误的地方,因为sqlalchemy不允许将布尔值附加到插入指令的集合

要更正错误,需要对查询调用其中一个执行方法,以返回ParkNone的实例。一个选项可能是^{},它来自文档:

Returns None if the query selects no rows. Raises sqlalchemy.orm.exc.MultipleResultsFound if multiple object identities are returned, or if multiple rows are returned for a query that returns only scalar values as opposed to full identity-mapped entities.

所以这条线可能变成:

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

相关问题 更多 >