完整教程:SQLAlchemy ORM 入门教程
1. 安装 SQLAlchemy
pip install sqlalchemy # 使用pip指令安装必要包
2. 创建数据库连接与基础配置
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# 创建数据库引擎(这里以 SQLite 为例,数据库文件为 test.db)
engine = create_engine('sqlite:///test.db', echo=True)
# 创建基类
Base = declarative_base()
# 创建会话类
SessionLocal = sessionmaker(bind=engine)
说明:
create_engine创建数据库连接引擎,echo=True可以打印执行的 SQL,方便调试。declarative_base()用于声明模型基类。sessionmaker用于创建数据库会话,后续操作通过 session 进行。
易错点:
- 数据库连接字符串格式不对会导致连接失败,注意不同数据库连接字符串不同。
sessionmaker必须绑定engine,否则无法操作数据库。
3. 定义 ORM 模型(创建表结构)
from sqlalchemy import Column, Integer, String
class User(Base):
__tablename__ = 'users' # 表名
id = Column(Integer, primary_key=True, index=True)
name = Column(String(50), nullable=False)
age = Column(Integer)
def __repr__(self):
return f""
说明:
User类继承自Base,代表数据库中的一张表。所有继承Base的类都会被存储到Base的metadata中。__tablename__指定表名。Column定义字段类型和约束。primary_key=True表示主键。nullable=False表示该字段不能为空。
易错点:
- 模型类必须继承
Base。 - 主键字段必须指定,否则表无法正常创建。
- 字段类型要和数据库类型对应,长度限制要合理。
4. 创建表(生成数据库表结构)
Base.metadata.create_all(engine)
说明:
- 这行代码会根据所有继承了
Base的模型类,在数据库中创建对应的表。 - 如果表已存在,不会重复创建。
5. 增删改查操作示例
说明: 历史背景(删除,查询等方法类似,增加操作不变)
在 SQLAlchemy 1.x 时代,ORM 查询主要使用 session.query():
user = session.query(User).filter(User.name == "Alice").first()
从 SQLAlchemy 1.4 开始,引入了新的 2.0 风格查询 API,推荐使用 select() 构建查询语句:
from sqlalchemy import select
stmt = select(User).where(User.name == "Alice") user = session.execute(stmt).scalars().first()
SQLAlchemy 1.4 提供了 两种风格同时兼容,但到了 2.0 正式版,session.query() 已被官方标记为 deprecated(弃用),未来版本可能会被完全移除。
以下操作均以新方法展示:
5.1 创建(插入)数据
with SessionLocal() as session:
new_user = User(name='Alice', age=30)
session.add(new_user)
session.commit()
说明:
- 使用
with可以自动关闭会话,避免资源泄漏。
易错点:
- 忘记 commit,数据不会保存。
5.2 查询数据
from sqlalchemy import select
with SessionLocal() as session:
stmt = select(User).where(User.name == 'Alice')
user = session.execute(stmt).scalars().first()
print(user)
易错点:
忘记
.scalars(),会得到 Row 对象而不是 User 实例。未判断返回值是否为
None,可能导致后续.id等访问报错。
5.3 更新数据
with SessionLocal() as session:
user = session.execute(select(User).where(User.name == 'Alice')).scalars().first()
if user:
user.age = 31
session.commit()
5.4 删除数据
with SessionLocal() as session:
user = session.execute(select(User).where(User.name == 'Alice')).scalars().first()
if user:
session.delete(user)
session.commit()
易错点:
直接执行
delete(User)不加where()会删除整张表。删除后忘记
commit(),操作不会生效。
6. 总结与易错事项提醒
| 操作环节 | 易错点与注意事项 |
|---|---|
| 数据库连接 | 连接字符串格式错误(sqlite:/// vs postgresql://);忘记设置 echo=True 调试;生产环境应使用连接池配置。 |
| 模型定义 | 忘记继承 Base;未定义 __tablename__;未设置主键导致 ORM 无法管理;字段类型和数据库不匹配。 |
| 创建表 | 忘记执行 Base.metadata.create_all(engine);开发阶段修改模型后需手动迁移(建议用 Alembic 管理迁移)。 |
| 会话管理 | 忘记 commit() 导致数据不保存;未 close() 或未用 with Session() as session: 导致连接泄漏;推荐用 sessionmaker() 生成独立会话。 |
| 查询操作 | 常见错用:继续用 session.query()(已弃用);忘记 .scalars() 提取 ORM 对象导致拿到 Row;未检查结果为空返回 None。 |
| 更新操作 | 直接修改对象但忘记 commit();update() 语句未加 .execution_options(synchronize_session="fetch") 导致会话状态不同步;更新条件写错导致批量修改全表数据。 |
| 删除操作 | delete() 条件写空导致全表删除;删除后忘记 commit();会话中已有该对象时未同步导致后续查询异常。 |
| 异常处理 | 未捕获 IntegrityError(主键/唯一约束冲突);出现异常后忘记 session.rollback() 导致会话进入无效状态。 |

浙公网安备 33010602011771号