FastAPI + SQLAlchemy 数据库对象转字典
def object_as_dict_list(db_list):return [{**object_as_dict(item)} for item in db_list]def object_as_dict(obj):return {column.name: getattr(obj, column.name) for column in obj.__table__.columns}
1. object_as_dict(obj)
函数(基础转换器)
def object_as_dict(obj):return {column.name: getattr(obj, column.name) for column in obj.__table__.columns}
工作原理:
obj.__table__.columns
:获取 SQLAlchemy 模型的所有列定义for column in obj.__table__.columns
:遍历每一列column.name
:获取列的名称(字段名)getattr(obj, column.name)
:获取对象在该字段上的值{column.name: getattr(obj, column.name) for ...}
:字典推导式,创建字段名到值的映射
示例:
假设有一个 User 模型:
class User(Base):__tablename__ = 'users'id = Column(Integer, primary_key=True)name = Column(String)email = Column(String)
调用 object_as_dict(user_obj)
会返回:
{'id': 1, 'name': 'Alice', 'email': 'alice@example.com'}
2. object_as_dict_list(db_list)
函数(批量转换器)
def object_as_dict_list(db_list):return [{**object_as_dict(item)} for item in db_list]
工作原理:
for item in db_list
:遍历数据库对象列表中的每个对象object_as_dict(item)
:将每个对象转换为字典{**object_as_dict(item)}
:使用字典解包创建新字典[...]
:列表推导式,将所有结果收集到新列表中
示例:
输入:[<User id=1>, <User id=2>]
输出:
[{'id': 1, 'name': 'Alice', 'email': 'alice@example.com'},{'id': 2, 'name': 'Bob', 'email': 'bob@example.com'}
]
为什么需要 {**dict}
解包操作?
安全性考虑:创建副本避免意外修改
# 没有解包的情况(潜在风险)
def risky_object_as_dict_list(db_list):return [object_as_dict(item) for item in db_list]result = risky_object_as_dict_list(users)
result[0]['name'] = 'Modified' # 这可能影响原始对象!# 使用解包的情况(安全)
def safe_object_as_dict_list(db_list):return [{**object_as_dict(item)} for item in db_list]result = safe_object_as_dict_list(users)
result[0]['name'] = 'Modified' # 安全,不影响原始对象
在 FastAPI 路由中使用:
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Sessionrouter = APIRouter()@router.get("/users")
async def get_users(db: Session = Depends(get_db)):# 查询数据库获取对象列表users = db.query(User).all()# 转换为字典列表(适合JSON响应)return object_as_dict_list(users)@router.get("/users/{user_id}")
async def get_user(user_id: int, db: Session = Depends(get_db)):# 查询单个对象user = db.query(User).filter(User.id == user_id).first()# 转换为字典return object_as_dict(user)