使用SQLAlchemy与Python:解决懒加载及参数错误问题
解决获取用户关注列表的两个SQLAlchemy问题
问题1:DetachedInstanceError 错误处理
错误原因
你拿到的user_obj已经脱离了数据库会话(Session),而following关系默认是懒加载模式——只有当实例绑定在活跃Session上时,才能触发后续的关联查询。一旦实例被Session关闭或移除,懒加载就会失败。
解决方案
有三种可行的处理方式,按需选择:
- 提前加载关联数据:获取用户时直接加载
following关系,避免后续懒加载from sqlalchemy.orm import joinedload # 查询用户时用joinedload预加载关注列表 user_obj = session.query(Users).options(joinedload(Users.following)).filter_by(id=目标用户ID).first() # 直接提取ID即可 following_ids = [user.id for user in user_obj.following] - 重新绑定会话:如果已经拿到脱离Session的
user_obj,把它重新加入活跃Session# session是当前正在使用的活跃数据库会话 session.add(user_obj) # 现在可以正常访问user_obj.following following_ids = [user.id for user in user_obj.following] - 修改加载策略:在定义
following关系时设置非懒加载(不推荐全局修改,仅适合特定场景)
在Users类的followers关系定义里,添加lazy='joined'或lazy='selectin',但会增加每次查询用户的开销。
问题2:直接查询UserFollowers表的ArgumentError 错误处理
错误原因
你用的是SQLAlchemy 2.0及以上版本,新版本的select()函数不需要把列放在列表里,直接传入列对象即可。旧版本select([列])的写法在新版本中会触发参数错误。
解决方案
去掉列外面的列表包裹,直接传入列对象:
# 正确的查询语句(SQLAlchemy 2.0+) stmt = select(UserFollowers.c.user_id).where(UserFollowers.c.follower_id == user_obj.id) # 执行查询并提取结果 following_ids = [row[0] for row in session.execute(stmt).all()]
完整示例代码
方式一:通过ORM关系获取关注ID
from sqlalchemy.orm import sessionmaker, joinedload from 你的模型模块 import Users, engine # 创建会话 Session = sessionmaker(bind=engine) session = Session() try: target_user_id = 123 # 替换成你要查询的用户ID user_obj = session.query(Users).options(joinedload(Users.following)).filter_by(id=target_user_id).first() if user_obj: following_ids = [user.id for user in user_obj.following] print(f"用户{target_user_id}关注的账号ID:{following_ids}") finally: session.close()
方式二:直接查询关联表获取关注ID
from sqlalchemy.orm import sessionmaker from 你的模型模块 import UserFollowers, engine # 创建会话 Session = sessionmaker(bind=engine) session = Session() try: target_user_id = 123 # 替换成你要查询的用户ID stmt = select(UserFollowers.c.user_id).where(UserFollowers.c.follower_id == target_user_id) result = session.execute(stmt).all() following_ids = [row[0] for row in result] print(f"用户{target_user_id}关注的账号ID:{following_ids}") finally: session.close()
内容的提问来源于stack exchange,提问作者RHO
相关产品推荐
相关产品推荐

