完整教程: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() 导致会话进入无效状态。
posted @ 2025-09-07 14:38  wzzkaifa  阅读(26)  评论(0)    收藏  举报