SQLAlchemy用Case语句时ORM实例元组适配FastAPI序列化问题
解决FastAPI序列化SQLAlchemy元组列表的问题
方法1:动态给ORM实例加字段(最简单)
查询返回的是(Post实例, is_editable值)的元组,直接遍历元组,把is_editable绑定到对应的Post实例上,Pydantic的orm_mode会自动识别这个字段。
is_editable_expr = case( [(Post.user_id == current_user.id, True)], else_=False, ).label("is_editable") query_result = db_session.query(Post, is_editable_expr).order_by(Post.created_at.desc()).join(User).all() # 处理结果,生成带is_editable的Post实例列表 posts_with_editable = [] for post, is_editable in query_result: post.is_editable = is_editable posts_with_editable.append(post) return posts_with_editable
方法2:转字典后再用Pydantic解析
如果不想修改ORM实例,就把每个元组转成包含所有字段的字典,再用Post模型验证。
from sqlalchemy.orm import class_mapper is_editable_expr = case( [(Post.user_id == current_user.id, True)], else_=False, ).label("is_editable") query_result = db_session.query(Post, is_editable_expr).order_by(Post.created_at.desc()).join(User).all() posts_data = [] for post, is_editable in query_result: # 把Post实例转成字典,包含所有列字段 post_dict = {col.key: getattr(post, col.key) for col in class_mapper(Post).columns} # 手动添加关联的user对象 post_dict["user"] = post.user # 加上is_editable字段 post_dict["is_editable"] = is_editable posts_data.append(post_dict) # 用Post模型解析每个字典,返回符合结构的列表 return [Post(**item) for item in posts_data]
方法3:优化查询语句(推荐,避免N+1查询)
用add_columns附加字段,同时用joinedload预加载user关联,减少数据库查询次数,再处理元组添加属性。
from sqlalchemy.orm import joinedload is_editable_expr = case( [(Post.user_id == current_user.id, True)], else_=False, ).label("is_editable") # 用add_columns添加is_editable,joinedload预加载user query = db_session.query(Post).add_columns(is_editable_expr)\ .order_by(Post.created_at.desc())\ .join(User)\ .options(joinedload(Post.user)) query_result = query.all() posts_with_editable = [] for post, is_editable in query_result: post.is_editable = is_editable posts_with_editable.append(post) return posts_with_editable
内容的提问来源于stack exchange,提问作者Aashay Amballi
相关产品推荐
相关产品推荐

