我的应用程序使用
fastapi==0.109.2
和 SQLAlchemy==2.0.27
。
@contextlib.contextmanager
def session_scope():
db_engine = create_engine(url) # echo=True if needed to see background SQL
Session = sessionmaker(bind=db_engine)
session = Session()
try:
yield session
session.commit()
except:
print("Error")
session.rollback()
raise
finally:
session.close()
然后我导入它并在此处使用它,如您所见,我在那里有 2 个打印,第一个显示实际数据,第二个(这是端点返回的内容)是空对象,我似乎找不到问题...
@router.get("/me")
def getusers(dependencies=Depends(JWTBearer())):
user = None
with session_scope() as sess:
x = sess.query(TokenTable).where(TokenTable.access_toke == dependencies).first()
user = sess.query(User).where(User.id == x.user_id).first()
print(user.__dict__)
print(user.__dict__)
return user
日志:
INFO: 127.0.0.1:40662 - "GET /users/me HTTP/1.1" 200 OK
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7f11ef2bfc40>, 'first': 'Deez', 'last': 'Nuts', 'email': '[email protected]', 'id': 2, 'is_active': True, 'coach': None}
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7f11ef2bfc40>}
INFO: 127.0.0.1:40662 - "GET /users/1/logs HTTP/1.1" 200 OK
INFO: 127.0.0.1:40656 - "GET /users/me HTTP/1.1" 200 OK
我阅读了很多 sqlachemy 文档,也在这里发现了一些问题,但没有一个涉及这个特定主题。
您面临的问题可能是因为一旦您使用 session_scope() as sess: 退出上下文管理器,您正在查询的会话就会关闭。这意味着,当您尝试在会话之外访问 user.dict 时,SQLAlchemy 无法延迟加载任何数据,因为会话不再活动。
要解决此问题,您可以尝试在会话中使用 joinload 立即加载数据。具体方法如下:
from sqlalchemy.orm import joinedload
@router.get("/me")
def getusers(dependencies=Depends(JWTBearer())):
user = None
with session_scope() as sess:
x = sess.query(TokenTable).where(TokenTable.access_toke == dependencies).first()
user = sess.query(User).options(joinedload('*')).where(User.id == x.user_id).first()
user_data = user.__dict__.copy() # create a copy of user data
print(user_data)
print(user_data)
return user_data
通过使用
joinedload('*')
,SQLAlchemy 将立即加载 User
的所有属性,因此即使会话关闭后您仍然可以稍后访问它们。