Pydantic增强SQLALchemy序列化(FastAPI直接输出SQLALchemy查询集)
1. 前言
在使用SQLAlchemy
过程中发现SQLAlchemy
的查询集没有类似django-orm
中values()
的功能,想通过Pydantic添加个实现类似的功能 还有就是pandas
明明支持SQLAlchemy
模块,但读取数据的时候还只能通过引擎+SQL语句的模式,实在不够优雅,想着查询集先直接出个字典类数据pandas直接解析
2. 定义SQLALchemy
python
from sqlalchemy.orm import declarative_base
# 创建基础模型类
Base = declarative_base()
# 定义一个简单的模型
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
3. 定义pydantic
python
class UserModel(BaseModel):
id: int = Field(..., description="用户ID")
name: str = Field(..., description="用户名")
age: int = Field(..., description="用户年龄")
model_config = {
'from_attributes': True
}
class UserListModel(RootModel):
root: list[UserModel]
model_config = {
'from_attributes': True
}
4. pydantic序列化SQLALchemy查询集
已经提前添加测试数据
python
# 创建数据库引擎
engine = create_engine('sqlite:///test.db')
# 创建表
Base.metadata.create_all(engine)
# 创建会话
Session = sessionmaker(bind=engine)
session = Session()
users = session.query(User).all()
# 将查询结果转换为Pydantic模型
user_list = UserListModel.model_validate(users)
# 转成字典
user_list.model_dump()
# 转成json
user_list.model_dump_json()
# 一步到位的写法
UserListModel.model_validate(users).model_dump_json()
5. 与FatAPI配合
python
app = FastAPI()
@app.get("/",response_model=UserListModel)
def read_root():
with session as db:
users = db.query(User).all()
return users
6. 总结
研究完发现这个方法感觉有点多此一举,除了可以用于FastAPI直接输出SQLAlchemy
查询集内容外,好像没啥优点了,能更优雅一点?还因为需要定义定义Pydantic反而更复杂一些,建议可以在有Pydantic+Pydantic项目中使用,尤其是FastAPI项目
7. 附录:传统使用方式
常规方式是在模型当中添加一个自定义to_dict()
的方法,然后通过列表迭代的方式重新组成查询集字典
python
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# 创建基础模型类
Base = declarative_base()
# 定义一个简单的模型
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
def to_dict(self):
return {
'id': self.id,
'name': self.name,
'age': self.age
}
# 创建数据库引擎
engine = create_engine('sqlite:///test.db')
# 创建表
Base.metadata.create_all(engine)
# 创建会话
Session = sessionmaker(bind=engine)
session = Session()
# 添加一些示例数据
new_user = User(name='John', age=30)
session.add(new_user)
session.commit()
# 查询数据并转换为字典
users = session.query(User).all()
user_dicts = [user.to_dict() for user in users]
# 打印结果
print(user_dicts)
# 关闭会话
session.close()