使用SQLModel和FastAPI实现英雄数据更新功能详解

使用SQLModel和FastAPI实现英雄数据更新功能详解

项目概述

本文将深入讲解如何使用SQLModel和FastAPI构建一个支持CRUD操作的RESTful API,重点聚焦在数据更新功能的实现。SQLModel是一个强大的Python库,它结合了SQLAlchemy和Pydantic的优点,能够简化数据库模型的定义和操作。

核心模型设计

英雄基础模型

首先定义了HeroBase模型作为所有英雄相关模型的基类,包含三个字段:

  • name: 英雄名称,设置为索引字段
  • secret_name: 英雄秘密身份
  • age: 英雄年龄,可选字段,也设置为索引
class HeroBase(SQLModel):
    name: str = Field(index=True)
    secret_name: str
    age: Optional[int] = Field(default=None, index=True)

数据库模型

Hero模型继承自HeroBase并添加了数据库特有字段:

  • id: 主键,自动生成
  • hashed_password: 存储加密后的密码
class Hero(HeroBase, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    hashed_password: str = Field()

数据传输模型

系统设计了多个数据传输模型以适应不同场景:

  • HeroCreate: 用于创建英雄,包含原始密码字段
  • HeroPublic: 用于返回给客户端的数据,不包含敏感信息
  • HeroUpdate: 专门用于更新操作,所有字段都是可选的

数据库配置

使用SQLite作为数据库,配置了以下参数:

  • check_same_thread=False: 允许多线程访问
  • echo=True: 输出SQL语句,方便调试
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
connect_args = {"check_same_thread": False}
engine = create_engine(sqlite_url, echo=True, connect_args=connect_args)

API端点实现

创建英雄

POST /heroes/端点接收HeroCreate数据,处理密码加密后存入数据库:

@app.post("/heroes/", response_model=HeroPublic)
def create_hero(hero: HeroCreate):
    hashed_password = hash_password(hero.password)
    with Session(engine) as session:
        extra_data = {"hashed_password": hashed_password}
        db_hero = Hero.model_validate(hero, update=extra_data)
        session.add(db_hero)
        session.commit()
        session.refresh(db_hero)
        return db_hero

查询英雄

实现了两个查询端点:

  1. GET /heroes/: 分页查询所有英雄
  2. GET /heroes/{hero_id}: 查询单个英雄详情

更新英雄

PATCH /heroes/{hero_id}端点实现了部分更新功能,这是本文的重点:

@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
def update_hero(hero_id: int, hero: HeroUpdate):
    with Session(engine) as session:
        db_hero = session.get(Hero, hero_id)
        if not db_hero:
            raise HTTPException(status_code=404, detail="Hero not found")
        hero_data = hero.model_dump(exclude_unset=True)
        extra_data = {}
        if "password" in hero_data:
            password = hero_data["password"]
            hashed_password = hash_password(password)
            extra_data["hashed_password"] = hashed_password
        db_hero.sqlmodel_update(hero_data, update=extra_data)
        session.add(db_hero)
        session.commit()
        session.refresh(db_hero)
        return db_hero

更新功能详解

部分更新实现原理

  1. 模型设计HeroUpdate模型中所有字段都是可选的,这允许客户端只发送需要更新的字段
  2. 数据处理:使用model_dump(exclude_unset=True)只获取客户端实际设置的字段
  3. 密码处理:如果包含密码字段,会单独处理加密逻辑
  4. 更新操作:使用sqlmodel_update方法智能更新模型字段

安全考虑

  • 密码字段不会直接存储,而是经过哈希处理
  • 更新操作使用PATCH而非PUT,符合RESTful最佳实践
  • 返回的数据模型HeroPublic不包含敏感信息

最佳实践建议

  1. 密码处理:示例中使用了简单的哈希函数,实际项目中应使用专业库如passlib
  2. 错误处理:对不存在的资源返回404状态码
  3. 分页查询:GET端点实现了基本的offset/limit分页
  4. 类型安全:充分利用Python类型提示提高代码可靠性

总结

通过这个示例,我们学习了如何使用SQLModel和FastAPI构建一个完整的CRUD API,特别是实现了符合RESTful规范的部分更新功能。SQLModel的强大之处在于它简化了数据库操作,同时保持了类型安全和代码简洁性。这种模式可以扩展到更复杂的业务场景中。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薄正胡Plains

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值