0%

SQLModel自学教程(7) - 自动ID与数据刷新

1.自动ID机制解析

1
2
3
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
  • 核心原理
    • 数据库层id为主键且不可为NULL
    • Python层使用Optional[int]允许id=None初始状态
    • 插入时自动生成自增ID(SQLite/PostgreSQL等支持)

2.模型定义规范

1
2
3
4
5
6
7
8
# Python 3.10+ 语法
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str

# Python 3.8+ 兼容写法
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)

要点说明

  • primary_key=True声明主键约束
  • default=None确保插入时无需显式指定ID
  • 自动映射到数据库自增字段(INTEGER PRIMARY KEY)

3.数据插入流程

graph TD
    A[创建实例] --> B[开启Session]
    B --> C[add() 添加对象]
    C --> D[commit() 提交事务]
    D --> E[refresh() 刷新对象]
  • 关键操作
    1
    2
    3
    4
    5
    hero = Hero(name="Spider-Boy")
    session.add(hero)
    session.commit()
    session.refresh(hero) # 获取生成的ID
    print(hero.id) # 输出如1
  • 提交后数据库自动分配ID
  • 必须执行refresh()获取最新状态

4.类型安全解决方案

1
2
3
4
5
6
7
8
9
10
11
# 基础模型(无ID约束)
class HeroBase(SQLModel):
name: str

# 数据库表模型
class Hero(HeroBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)

# 读取模型(强制ID存在)
class HeroRead(HeroBase):
id: int

优势

  • 写入时使用Hero模型允许id=None
  • 读取时使用HeroRead确保id必为int
  • 避免类型检查错误

5.常见错误处理

1
2
3
4
5
# 错误场景:未设置default=None
class Hero(SQLModel, table=True):
id: Optional[int] = Field(primary_key=True) # 缺少默认值

# 插入时报错:NOT NULL constraint failed

解决方案

  • 必须添加default=None
  • 检查多主键配置(避免字段冲突)

6.高级配置选项

1
2
3
4
5
6
# 自定义自增序列(PostgreSQL)
id: Optional[int] = Field(
default=None,
primary_key=True,
sa_column=Column(Integer, Sequence('hero_id_seq'))
)
  • 支持不同数据库的自增机制
  • 通过sa_column配置底层SQLAlchemy列

提示:完整示例代码建议参考官方文档,生产环境推荐使用多模型策略保证类型安全