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 Session

router = 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)
相关推荐
极限实验室23 分钟前
APM(一):Skywalking 与 Easyearch 集成
数据库·云原生
饕餮争锋28 分钟前
SQL条件中WHERE 1=1 的功能
数据库·sql
玄斎1 小时前
MySQL 单表操作通关指南:建库 / 建表 / 插入 / 增删改查
运维·服务器·数据库·学习·程序人生·mysql·oracle
编织幻境的妖1 小时前
SQL查询连续登录用户方法详解
java·数据库·sql
编程小Y2 小时前
MySQL 与 MCP 集成全解析(核心原理 + 实战步骤 + 应用场景)
数据库·mysql·adb
零度@2 小时前
SQL 调优全解:从 20 秒到 200 ms 的 6 步实战笔记(附脚本)
数据库·笔记·sql
Miss_Chenzr3 小时前
Springboot优卖电商系统s7zmj(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
lvbinemail3 小时前
Grafana模板自动复制图表
数据库·mysql·zabbix·grafana·监控
Miss_Chenzr3 小时前
Springboot旅游景区管理系统9fu3n(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·旅游
小虾米vivian3 小时前
dmetl5 运行失败,提示违反协议?
数据库·达梦数据库