快速入门 SQLAlchemy:Python ORM 基础 – wiki基地


快速入门 SQLAlchemy:Python ORM 基础

欢迎来到 SQLAlchemy 的世界!如果你是一位 Python 开发者,并且需要与数据库进行交互,那么 SQLAlchemy 几乎是你绕不开的选择。它是一款功能强大、灵活且成熟的数据库工具包和对象关系映射(ORM)库。本文将带你快速入门 SQLAlchemy 的基础知识,重点聚焦于其 ORM 部分,帮助你理解如何使用 Python 对象来操作数据库。

目录

  1. 引言:什么是 ORM?为什么选择 SQLAlchemy?
    • ORM 的概念
    • 为什么使用 ORM?
    • SQLAlchemy 的优势
  2. 安装与准备
  3. SQLAlchemy 的核心组件概览
    • Engine (引擎)
    • MetaData (元数据)
    • Table (表)
    • Column (列)
    • Core (核心) 与 ORM 的关系
  4. 使用 ORM:声明式模型 (Declarative)
    • 定义数据库模型 (表映射到类)
    • 数据类型映射
    • 主键、外键、索引等约束
  5. 创建数据库和表结构
    • 通过模型生成表
  6. 会话 (Session):ORM 的工作单元
    • 理解 Session 的作用
    • 创建 Session 工厂
    • 使用 Session
  7. CRUD 操作 (增、删、改、查)
    • 创建 (Create): 添加新数据
    • 查询 (Read):
      • 基础查询
      • 过滤 (filter)
      • 排序 (order_by)
      • 限制结果数量 (limit, offset)
      • 按主键获取
      • 查询单个结果 (first, one, scalar)
    • 更新 (Update): 修改现有数据
    • 删除 (Delete): 移除数据
  8. 事务管理:提交与回滚
    • session.add(), session.commit(), session.rollback()
    • 理解事务边界
  9. 关联关系 (Relationships)
    • 一对多关系示例
    • 定义 relationship()
    • 通过关系访问数据
  10. 最佳实践:使用上下文管理器
  11. 总结与下一步

1. 引言:什么是 ORM?为什么选择 SQLAlchemy?

ORM 的概念

ORM,全称 Object-Relational Mapping(对象关系映射),是一种编程技术,用于在面向对象编程语言和关系型数据库之间转换数据。简单来说,ORM 允许你使用编程语言中的对象来代表数据库中的表和记录,通过操作这些对象来间接操作数据库。

想象一下,你的数据库里有一个 users 表,包含 id, name, email 等字段。在不使用 ORM 的情况下,你需要写 SQL 语句来查询、插入、更新或删除数据:

sql
SELECT id, name, email FROM users WHERE id = 1;
INSERT INTO users (name, email) VALUES ('Alice', '[email protected]');
UPDATE users SET email = '[email protected]' WHERE id = 1;
DELETE FROM users WHERE id = 1;

然后,在 Python 代码中,你需要执行这些 SQL 语句,并处理返回的结构化数据(通常是元组或字典)。

使用 ORM,你可以创建一个 User 类,它的实例对应于 users 表中的一行记录。操作数据就变成了操作 User 对象:

“`python

伪代码,使用 ORM 的概念

user = session.query(User).filter(User.id == 1).first() # 查询
new_user = User(name=’Alice’, email=’[email protected]’) # 创建
session.add(new_user)
session.commit() # 保存到数据库
“`

这种方式更加符合面向对象的思维,减少了直接编写和管理 SQL 的繁琐,提高了开发效率。

为什么使用 ORM?

  • 抽象数据库细节: 你不需要关心底层数据库(MySQL, PostgreSQL, SQLite 等)的特定 SQL 语法差异,ORM 会为你处理。
  • 提高开发效率: 使用面向对象的方式操作数据比拼接 SQL 字符串更直观、更快速。
  • 代码更易维护: 模型定义集中,业务逻辑直接作用于对象,代码结构更清晰。
  • 安全性: ORM 通常能帮助预防 SQL 注入等安全问题。
  • 处理关联关系: ORM 擅长处理数据库表之间的复杂关联关系(一对一、一对多、多对多),使得通过对象属性就能访问关联的数据。

SQLAlchemy 的优势

SQLAlchemy 是 Python 世界中最流行和功能最强大的 ORM 之一。它的主要优势包括:

  • 灵活性: SQLAlchemy 提供了两个主要的组件:CoreORM。Core 提供了数据库抽象层和 SQL 构建表达式,你可以完全脱离 ORM,只使用 Core 来构建和执行 SQL。ORM 则在 Core 的基础上提供了对象映射能力。这意味着你可以根据需求选择不同层次的抽象,甚至在需要时混用 Core 和 ORM。
  • 功能丰富: 支持几乎所有主流数据库,提供了强大的查询语言、事务管理、连接池、模式定义(Schema Definition Language, SDL)、迁移工具集成等。
  • 高性能: SQLAlchemy 在性能方面表现优异,提供了延迟加载、积极加载等策略来优化数据加载效率。
  • 成熟稳定: 拥有庞大的用户社区和活跃的开发,久经考验。
  • 高度可配置: 提供了大量的配置选项,以满足各种复杂的场景需求。

对于刚入门的开发者来说,SQLAlchemy 的强大功能可能会让人觉得有点复杂。但一旦掌握了其核心概念,特别是 ORM 部分,你就能体会到它带来的便利和效率。本文将专注于 ORM 的基础,让你快速上手。

2. 安装与准备

在开始之前,你需要安装 SQLAlchemy。推荐使用 pip 工具进行安装。

bash
pip install SQLAlchemy

为了演示,我们还需要一个数据库驱动。SQLite 是一个轻量级的、基于文件的数据库,非常适合入门和测试,无需额外的服务器进程。Python 标准库自带了 SQLite 驱动。所以,只需要安装 SQLAlchemy 即可。

如果你想连接其他数据库,例如 PostgreSQL 或 MySQL,你需要安装相应的驱动:

  • PostgreSQL: pip install psycopg2-binary
  • MySQL: pip install PyMySQL (或者 mysql-connector-python)

在本文中,我们将使用 SQLite 进行演示。

3. SQLAlchemy 的核心组件概览

虽然本文主要讲 ORM,但理解 SQLAlchemy Core 的几个基础概念对于理解 ORM 构建在哪上面是很有帮助的。

  • Engine (引擎): Engine 是数据库连接的入口点。它负责管理数据库连接池以及提供连接到数据库的能力。你可以通过一个 URL 来指定连接的数据库类型、地址、用户名、密码等信息。
    “`python
    from sqlalchemy import create_engine

    SQLite 数据库,文件名为 example.db

    engine = create_engine(‘sqlite:///example.db’)

    PostgreSQL 示例 (需要替换为你的连接信息)

    engine = create_engine(‘postgresql://user:password@host:port/dbname’)

    MySQL 示例 (需要替换为你的连接信息)

    engine = create_engine(‘mysql+pymysql://user:password@host:port/dbname’)

    “`

  • MetaData (元数据): MetaData 是一个容器对象,用于收集关于数据库模式(schema)的信息,比如表、列、约束等。你可以通过它来定义数据库结构,也可以通过它来反射(reflect)现有数据库的结构。

  • Table (表): Table 对象代表数据库中的一张表。它与 MetaData 关联,并包含 Column 对象来定义表的字段。

  • Column (列): Column 对象代表表中的一列。它与数据类型以及各种约束(如主键 primary_key=True、非空 nullable=False、唯一 unique=True、默认值 default、索引 index=True 等)关联。

  • Core (核心) 与 ORM 的关系: SQLAlchemy Core 提供了低层次的数据库操作能力,包括连接管理、SQL 表达式构建(例如 select([users_table.c.name]))、事务管理。SQLAlchemy ORM 在 Core 之上构建,它将数据库表映射到 Python 类,将行映射到类的实例,将列映射到类的属性。ORM 通过 Session 来管理对象的生命周期和数据库同步。

在 ORM 中,我们通常使用声明式系统 (Declarative) 来定义模型,这个系统会自动为你创建 MetaData、Table 和 Column 对象,隐藏了部分 Core 的底层细节,使得定义模型更加简洁直观。

4. 使用 ORM:声明式模型 (Declarative)

SQLAlchemy 的声明式系统允许你将数据库表定义和 ORM 映射定义合二为一,通过简单的 Python 类来实现。这是现代 SQLAlchemy ORM 开发中最常用的方式。

定义数据库模型 (表映射到类)

首先,我们需要一个基类,它是所有声明式模型的基石。

“`python
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
“`

declarative_base() 返回一个基类,你的所有模型类都应该继承自它。这个基类会维护一个 MetaData 对象(可以通过 Base.metadata 访问),并知道如何将你的类映射到数据库表。

接下来,我们定义一个简单的 User 模型,对应数据库中的 users 表。

“`python
from sqlalchemy import Column, Integer, String

class User(Base):
tablename = ‘users’ # tablename 是必须的,指定了数据库中的表名

id = Column(Integer, primary_key=True) # 定义一个整型主键列
name = Column(String, nullable=False) # 定义一个字符串列,非空
email = Column(String, unique=True) # 定义一个字符串列,唯一

# 可选:用于打印对象时的友好表示
def __repr__(self):
    return f"<User(id={self.id}, name='{self.name}', email='{self.email}')>"

“`

上面的代码定义了一个名为 User 的 Python 类,它继承自 Base。通过 __tablename__ 指定了它映射到数据库的 users 表。类属性 id, name, email 使用 Column 函数定义,映射到表中的同名列。

数据类型映射

SQLAlchemy 支持丰富的数据库数据类型,并且在不同的数据库后端之间进行抽象。常用的数据类型包括:

  • Integer: 整型
  • String(length): 变长字符串,通常需要指定最大长度 length
  • Text: 不限长度的文本
  • Boolean: 布尔型
  • Date: 日期
  • DateTime: 日期和时间
  • Time: 时间
  • Float: 浮点型
  • Numeric(precision, scale): 定点十进制数
  • LargeBinary / Blob: 二进制大对象

你可以根据数据库字段的类型选择合适的 SQLAlchemy 类型。

主键、外键、索引等约束

Column 定义中,你可以传递额外的参数来指定列的约束:

  • primary_key=True: 将该列设为主键。
  • nullable=False: 将该列设为非空。
  • unique=True: 要求该列的值在表中唯一。
  • default=value: 设置该列的默认值。
  • index=True: 为该列创建索引,以加快查询速度。
  • ForeignKey('tablename.columnname'): 定义外键,关联到另一张表的某一列。需要导入 ForeignKey

5. 创建数据库和表结构

定义好模型类后,我们需要将这些模型“翻译”成实际的数据库表。Base.metadata 包含了所有通过 Base 定义的模型信息。我们可以利用这个元数据对象,通过 Engine 来创建所有未创建的表。

“`python

假设我们已经有了 engine 对象,并且定义了 User 模型

from sqlalchemy import create_engine, Column, Integer, String

from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base): … (同上)

确保导入了 Base 和 engine

from your_models_file import Base # 如果模型定义在其他文件

from your_engine_setup import engine # 如果 engine 在其他地方创建

创建所有在 Base.metadata 中注册的表

checkfirst=True 表示创建前先检查表是否存在,如果存在则跳过

Base.metadata.create_all(engine, checkfirst=True)

print(“数据库表已创建或已存在。”)
“`

执行这段代码后,如果 example.db 文件不存在,它会被创建;如果文件存在但其中没有 users 表,那么 users 表会被创建。如果 users 表已经存在,则什么也不会发生(因为 checkfirst=True)。

6. 会话 (Session):ORM 的工作单元

在 SQLAlchemy ORM 中,Session 是核心概念。Session 代表了一次与数据库的对话,它负责:

  • 跟踪对象的状态: 哪些对象被修改了,哪些是新的,哪些将被删除。
  • 构建 SQL 语句: 根据你对对象的操作,生成相应的 INSERT, SELECT, UPDATE, DELETE 语句。
  • 管理事务: 协调多个操作作为一个原子单元(事务),要么全部成功(提交 commit),要么全部失败(回滚 rollback)。
  • 提供查询接口: 使用 session.query() 来构建查询语句。

Session 本身并不是线程安全的,每个线程通常应该有自己的 Session。推荐的做法是使用 sessionmaker 创建一个 Session 工厂,然后每次需要时从工厂获取一个新的 Session 实例。

“`python
from sqlalchemy.orm import sessionmaker

创建一个 Session 工厂

bind 参数指定了 Session 要绑定的 Engine

SessionLocal = sessionmaker(bind=engine)

现在你可以通过 SessionLocal() 来获取一个 Session 实例

session = SessionLocal()

可以在这里进行数据库操作…

最后,关闭 Session

session.close()
“`

获取 Session 后,所有通过该 Session 进行的数据库操作都将在这个 Session 的上下文中进行,直到你提交、回滚或关闭它。

7. CRUD 操作 (增、删、改、查)

有了 Engine、Base 和 Session,我们就可以开始进行数据库的 CRUD 操作了。

创建 (Create):添加新数据

要向数据库中添加一条新记录,只需创建一个模型类的实例,设置好属性值,然后通过 session.add() 方法将其添加到 Session 中。最后,调用 session.commit() 将更改保存到数据库。

“`python

假设我们已经有了 SessionLocal 工厂

session = SessionLocal() # 获取 Session 实例

创建一个新的 User 对象

new_user = User(name=’Alice’, email=’[email protected]’)

将对象添加到 Session 中

session.add(new_user)

提交 Session,将对象保存到数据库

session.commit()

print(f”用户 {new_user.name} 已添加到数据库,ID 是 {new_user.id}”) # ID 在commit后通常会自动生成并填充到对象中

再次添加一个用户

another_user = User(name=’Bob’, email=’[email protected]’)
session.add(another_user)
session.commit()
print(f”用户 {another_user.name} 已添加到数据库,ID 是 {another_user.id}”)

可以一次添加多个对象

session.add_all([user1, user2, user3])

session.commit()

“`

注意,session.add() 只是将对象放到了 Session 的“暂存区”,更改尚未写入数据库。只有调用 session.commit() 后,SQLAlchemy 才会生成 INSERT 语句并执行,将数据持久化。

查询 (Read):

查询是 ORM 中最常用的操作。SQLAlchemy ORM 提供了强大的查询 API。我们使用 session.query() 方法,传入要查询的模型类。

“`python

假设我们已经添加了一些用户数据

查询所有用户

all_users = session.query(User).all()
print(“\n— 所有用户 —“)
for user in all_users:
print(user)

按主键查询单个用户

user_by_id = session.query(User).get(1) # get() 方法直接按主键查询
if user_by_id:
print(f”\n— ID 为 1 的用户 —“)
print(user_by_id)

过滤查询 (filter)

查询名字是 ‘Alice’ 的用户

alice = session.query(User).filter(User.name == ‘Alice’).first() # first() 返回第一个匹配项或 None
if alice:
print(f”\n— 名字是 Alice 的用户 —“)
print(alice)

查询 ID 大于 1 的用户

users_gt_1 = session.query(User).filter(User.id > 1).all()
print(f”\n— ID 大于 1 的用户 —“)
for user in users_gt_1:
print(user)

组合过滤条件 (使用 and_, or_)

from sqlalchemy import and_, or_

查询名字是 Bob 且 email 是 [email protected] 的用户

bob = session.query(User).filter(and_(User.name == ‘Bob’, User.email == ‘[email protected]’)).first()
if bob:
print(f”\n— 名字是 Bob 且 email 是 [email protected] 的用户 —“)
print(bob)

查询名字是 Alice 或 Bob 的用户

alice_or_bob = session.query(User).filter(or_(User.name == ‘Alice’, User.name == ‘Bob’)).all()
print(f”\n— 名字是 Alice 或 Bob 的用户 —“)
for user in alice_or_bob:
print(user)

使用 like 进行模糊匹配

users_with_example_email = session.query(User).filter(User.email.like(‘%@example.com’)).all()
print(f”\n— email 包含 @example.com 的用户 —“)
for user in users_with_example_email:
print(user)

排序 (order_by)

按名字升序排序

users_ordered_by_name = session.query(User).order_by(User.name).all()
print(“\n— 按名字升序排序的用户 —“)
for user in users_ordered_by_name:
print(user)

按 ID 降序排序

users_ordered_desc = session.query(User).order_by(User.id.desc()).all()
print(“\n— 按 ID 降序排序的用户 —“)
for user in users_ordered_desc:
print(user)

限制结果数量 (limit, offset)

获取前两个用户

first_two_users = session.query(User).limit(2).all()
print(“\n— 前两个用户 —“)
for user in first_two_users:
print(user)

跳过第一个,获取接下来的两个用户

next_two_users = session.query(User).offset(1).limit(2).all()
print(“\n— 跳过第一个,获取接下来的两个用户 —“)
for user in next_two_users:
print(user)

查询单个结果

first(): 返回第一个匹配项或 None

one(): 返回一个匹配项,如果没有匹配项或有多个匹配项则抛出异常

scalar(): 返回一个单列结果的第一个值,如果没有匹配项或有多个值则抛出异常

注意:使用 one() 和 scalar() 需要确保查询结果是唯一的或只有一个值

获取用户数量

user_count = session.query(User).count() # count() 返回结果数量
print(f”\n— 用户总数 —“)
print(user_count)
“`

查询方法通常是链式的,你可以将 filter(), order_by(), limit(), offset() 等方法组合使用。

更新 (Update):修改现有数据

更新数据非常简单:先通过查询获取到要修改的对象,然后直接修改对象的属性值,最后调用 session.commit() 将更改保存到数据库。

“`python

假设我们要更新 ID 为 1 的用户的邮箱

user_to_update = session.query(User).get(1)
if user_to_update:
print(f”\n— 更新前用户 —“)
print(user_to_update)

user_to_update.email = '[email protected]'
# user_to_update.name = 'Alicia' # 可以修改多个属性

session.commit() # 提交更改

print(f"用户 ID 为 1 的邮箱已更新。")
print(user_to_update) # 对象属性已被更新

“`

在调用 session.commit() 之前,修改只存在于 Session 中。commit() 会检测所有被修改的对象,并生成相应的 UPDATE 语句执行。

删除 (Delete):移除数据

要删除数据,首先获取要删除的对象,然后使用 session.delete() 将其标记为待删除,最后调用 session.commit()

“`python

假设我们要删除 ID 为 2 的用户

user_to_delete = session.query(User).get(2)
if user_to_delete:
print(f”\n— 删除用户 —“)
print(user_to_delete)

session.delete(user_to_delete) # 将对象标记为删除

session.commit() # 执行删除操作

print(f"用户 ID 为 2 的用户已删除。")

验证是否删除

deleted_user = session.query(User).get(2)
print(f”尝试获取 ID 为 2 的用户: {deleted_user}”) # 应该返回 None
“`

session.delete() 只是将对象从 Session 中移除,并标记其在提交时应被删除。session.commit() 会生成 DELETE 语句并执行。

8. 事务管理:提交与回滚

Session 在内部管理着一个事务。你通过 session.add(), session.delete(), 修改对象属性等操作对 Session 进行更改,这些更改都暂存在 Session 中,尚未写入数据库。

  • session.commit(): 提交当前事务。这会将 Session 中的所有挂起更改(添加、删除、修改)作为一个原子操作发送到数据库。如果所有操作都成功,数据就被永久保存。
  • session.rollback(): 回滚当前事务。这会撤销 Session 中所有尚未提交的更改,将 Session 的状态恢复到上次提交或开始时的状态,数据库中的数据不受影响。这常用于处理错误情况。
  • session.close(): 关闭 Session。释放与之关联的数据库连接。一个关闭的 Session 不能再进行操作。

重要概念:

  • 事务的原子性: 事务中的所有操作要么全部成功,要么全部失败。如果在 commit() 过程中发生错误,SQLAlchemy 会自动回滚事务,确保数据库保持一致状态。
  • Session 的生命周期: Session 应该是短lived(生命周期短)的。在一个请求、一个任务或一个函数执行的范围内创建 Session,完成数据库操作后立即提交或回滚,并关闭 Session。不要在整个应用程序生命周期中重用同一个 Session。

9. 关联关系 (Relationships)

关系型数据库的强大之处在于表之间的关联。ORM 的一个主要优势就是能够方便地处理这些关联,使得你可以通过对象属性来访问关联的对象或集合。

让我们添加一个 Article 模型,并与 User 模型建立一对多关系:一个用户可以发表多篇文章,一篇文章只能由一个用户发表。

首先,修改 User 模型,添加一个属性来表示该用户的所有文章:

“`python
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship # 导入 relationship

class User(Base):
tablename = ‘users’

id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
email = Column(String, unique=True)

# 定义与 Article 的一对多关系
# 'Article' 是关联的模型类名
# backref='author' 在 Article 模型中创建一个 'author' 属性,指向关联的 User 对象
articles = relationship('Article', backref='author')

def __repr__(self):
    return f"<User(id={self.id}, name='{self.name}')>" # 简化表示

“`

然后,创建 Article 模型,并添加一个外键列指向 users 表的主键,以及一个属性来表示关联的作者:

“`python
from sqlalchemy import Text

class Article(Base):
tablename = ‘articles’

id = Column(Integer, primary_key=True)
title = Column(String, nullable=False)
content = Column(Text)

# 定义外键列,关联到 users 表的 id 列
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)

# backref='articles' 在 User 模型中创建了 articles 属性,我们不需要在这里再次定义 relationship
# author = relationship('User', backref='articles') # 这一行是可选的,如果 User 模型中已经定义了 backref='author'

def __repr__(self):
    return f"<Article(id={self.id}, title='{self.title[:20]}...', user_id={self.user_id})>"

“`

重新创建表结构 (或者使用迁移工具,但入门阶段直接创建更简单)

因为我们添加了新的 Article 模型,需要重新创建表(或确保新表被创建)。如果 users 表已经存在,create_all 会跳过它,但会创建 articles 表。

“`python

确保导入了 Article 模型

from your_models_file import Article # 如果模型定义在其他文件

重新创建所有表(会先检查是否存在)

Base.metadata.create_all(engine, checkfirst=True)

print(“Article 表已创建或已存在。”)
“`

通过关系访问数据

定义好关系后,你可以像访问普通属性一样访问关联的对象或集合。

“`python

假设我们已经有了 SessionLocal 工厂和一些 User 和 Article 数据

添加一些文章

user1 = session.query(User).get(1) # 获取 ID 为 1 的用户 (Alice)

if user1:
article1 = Article(title=’SQLAlchemy Basics’, content=’…’, author=user1) # 通过 relationship 设置作者
article2 = Article(title=’ORM Concepts’, content=’…’, user_id=user1.id) # 或者通过外键设置

session.add_all([article1, article2])
session.commit()
print("添加了两篇文章。")

查询用户及其文章 (通过 relationship)

user_with_articles = session.query(User).get(1)
if user_with_articles:
print(f”\n— 用户 {user_with_articles.name} 的文章 —“)
# 访问 user.articles 属性,SQLAlchemy 会自动执行一次查询来加载这些文章(延迟加载)
for article in user_with_articles.articles:
print(f”- {article.title}”)

查询文章及其作者 (通过 relationship/backref)

article_with_author = session.query(Article).filter(Article.title == ‘SQLAlchemy Basics’).first()
if article_with_author:
print(f”\n— 文章 ‘{article_with_author.title}’ 的作者 —“)
# 访问 article.author 属性
print(f”作者: {article_with_author.author.name}”)

另一种方式通过外键查询

article_explicit_join = session.query(Article).filter(Article.title == ‘ORM Concepts’).first()
if article_explicit_join and article_explicit_join.user_id:
author_from_fk = session.query(User).get(article_explicit_join.user_id)
print(f”文章 ‘{article_explicit_join.title}’ 的作者 (通过外键查询): {author_from_fk.name}”)
“`

使用 relationship 极大地简化了跨表查询和数据访问。当你访问 user.articles 时,SQLAlchemy 会在幕后执行一个 SELECT * FROM articles WHERE user_id = ? 的查询。当你访问 article.author 时,它会执行 SELECT * FROM users WHERE id = ? 的查询。这种默认行为称为延迟加载 (Lazy Loading),它只在属性被访问时才去加载数据。对于一对多关系,user.articles 返回一个列表,而对于多对一关系(通过 backref 或单独定义 relationship),article.author 返回单个对象或 None

10. 最佳实践:使用上下文管理器

手动管理 Session 的 close() 调用容易出错,特别是在代码中发生异常时。推荐使用 Python 的上下文管理器 (with 语句) 来确保 Session 在使用完毕后总是被正确关闭,即使发生错误也能回滚。

你可以为 sessionmaker 创建的 SessionLocal 添加一个函数,使其可以作为上下文管理器使用:

“`python
from sqlalchemy.orm import Session

… SessionLocal = sessionmaker(bind=engine) …

定义一个函数来获取 Session 并使用上下文管理器

def get_db():
db = SessionLocal()
try:
yield db # 生成 Session 实例
finally:
db.close() # 无论如何都关闭 Session

如何使用:

with get_db() as session:

# 在这里进行所有数据库操作,如查询、添加、修改、删除

users = session.query(User).all()

for user in users:

print(user)

# 如果需要提交,手动调用 commit()

# session.commit()

# Session 在 with 块结束时自动关闭

“`

在实际应用中,特别是 Web 框架(如 FastAPI 或 Flask)中,通常会集成这种模式,确保每个请求都有一个独立的、正确管理生命周期的数据库 Session。在一个 with 块中进行所有操作,并在块的最后统一 commit()rollback()(通常由框架处理异常自动回滚)。

11. 总结与下一步

恭喜你!通过阅读本文,你已经快速入门了 SQLAlchemy 的 ORM 基础知识,包括:

  • ORM 的概念和 SQLAlchemy 的优势
  • Engine 的作用
  • 使用声明式系统定义模型 (表映射到类)
  • 常见的数据类型和列约束
  • 如何通过模型生成数据库表
  • Session 作为 ORM 的工作单元
  • 使用 Session 进行基本的 CRUD 操作 (添加、查询、更新、删除)
  • 理解和管理事务 (commit, rollback)
  • 定义和使用一对多关联关系 (relationship, ForeignKey)
  • 使用上下文管理器管理 Session

这只是 SQLAlchemy 功能的冰山一角。接下来,你可以深入学习:

  • 更复杂的查询: 连接 (Join)、分组 (Group By)、聚合函数 (Sum, Avg, Count 等)、子查询。
  • 加载策略: 延迟加载 (Lazy Loading)、立即加载 (Eager Loading)、联合加载 (Joined Loading) 等,以优化查询性能。
  • 多对多关系 的定义和使用。
  • 继承映射: 如何将类继承结构映射到数据库表。
  • SQLAlchemy Core: 学习如何直接使用 Core 来构建和执行 SQL 表达式,这在某些复杂或需要高性能的场景下非常有用。
  • 数据库迁移工具: 如 Alembic,用于管理数据库模式随时间的变化。
  • 连接池配置: 优化数据库连接的使用。

通过不断实践和深入学习,你将能够充分发挥 SQLAlchemy 的强大功能,更高效、更优雅地处理数据库交互任务。

现在,就开始动手编写代码,将这些知识应用到你的项目中吧!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部