SQLAlchemy ORM 超全教程

目录

    • 前言
    • [1 ORM 概念](#1 ORM 概念)
      • [主流 ORM 对比](#主流 ORM 对比)
    • [2 SQLAlchemy 分层架构](#2 SQLAlchemy 分层架构)
    • [3 环境安装 & 数据库准备](#3 环境安装 & 数据库准备)
    • [4 基础配置文件](#4 基础配置文件)
    • [5 定义 ORM 模型(一对多示例:部门 & 员工)](#5 定义 ORM 模型(一对多示例:部门 & 员工))
    • [6 CRUD 增删改查完整示例](#6 CRUD 增删改查完整示例)
      • [6.1 新增 Create](#6.1 新增 Create)
      • [6.2 查询 Read](#6.2 查询 Read)
      • [6.3 更新 Update](#6.3 更新 Update)
      • [6.4 删除 Delete](#6.4 删除 Delete)
    • [7 表关联关系详解](#7 表关联关系详解)
      • [7.1 一对多 / 多对一(最常用)](#7.1 一对多 / 多对一(最常用))
      • [7.2 一对一](#7.2 一对一)
      • [7.3 多对多(中间表 Table)](#7.3 多对多(中间表 Table))
      • [relationship 核心参数](#relationship 核心参数)
    • [8 sqlacodegen 逆向生成模型(已有数据库自动生成类)](#8 sqlacodegen 逆向生成模型(已有数据库自动生成类))
      • [8.1 安装工具](#8.1 安装工具)
      • [8.2 代码自动生成模型](#8.2 代码自动生成模型)
    • [9 本章总结](#9 本章总结)

前言

SQLAlchemy 是 Python 最成熟 ORM 框架,分为 Core 底层 SQL 表达式、ORM 对象映射两层。本章讲解引擎 / 会话、模型定义、增删改查、一对多 / 一对一 / 多对多关联、sqlacodegen 逆向生成模型,适配 FastAPI 项目。

1 ORM 概念

ORM(对象关系映射):数据库表 ↔ Python 类,行 ↔ 对象,无需手写原生 SQL,屏蔽 MySQL/PostgreSQL 数据库差异。

主流 ORM 对比

表格

工具 适用场景
SQLAlchemy 通用、复杂查询、FastAPI 同步首选
Tortoise-ORM 纯异步 FastAPI 项目
Django ORM 仅 Django 框架
SQLModel 简化版 SQLAlchemy+Pydantic

2 SQLAlchemy 分层架构

  1. DBAPI:底层数据库驱动(pymysql/psycopg2)
  2. Core 层:Engine 引擎、连接池、SQL 表达式、字段类型
  3. ORM 层:对象映射、relationship 表关联

核心组件

  1. Engine:数据库连接入口,管理连接池
  2. Base:所有模型父类,统一管理表元数据
  3. Session:数据库会话,执行 CRUD、事务提交回滚

3 环境安装 & 数据库准备

bash 复制代码
# ORM核心 + MySQL驱动
pip install sqlalchemy pymysql

提前创建 MySQL 数据库:create database fastapi_db charset utf8mb4;

4 基础配置文件

base.py(模型基类)

python 复制代码
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

database.py(引擎、会话工厂)

python 复制代码
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 连接字符串格式 mysql+pymysql://账号:密码@地址:端口/库名
DB_URL = "mysql+pymysql://root:123456@localhost:3306/fastapi_db"

engine = create_engine(
    DB_URL,
    echo=True, # 开发打印SQL,生产关闭
    pool_pre_ping=True # 自动检测失效连接
)
# 会话工厂,autocommit关闭必须手动commit
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

5 定义 ORM 模型(一对多示例:部门 & 员工)

models.py

python 复制代码
from sqlalchemy import Column, Integer, String, Date, ForeignKey
from sqlalchemy.orm import relationship
from base import Base

# 部门表 一对多主表
class Department(Base):
    __tablename__ = "departments"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False, unique=True)
    location = Column(String(100))
    # 一对多关联员工
    employees = relationship("Employee", back_populates="department", lazy="selectin")

# 员工表 多对子表
class Employee(Base):
    __tablename__ = "employees"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False)
    age = Column(Integer)
    hire_date = Column(Date)
    # 外键关联部门
    department_id = Column(Integer, ForeignKey("departments.id", ondelete="RESTRICT"), nullable=False)
    # 反向关联部门,uselist=False单对象
    department = relationship("Department", back_populates="employees", lazy="joined")

创建数据表

python 复制代码
from base import Base
from database import engine
import models # 必须导入模型,否则无法识别表

def create_tables():
    Base.metadata.create_all(bind=engine)

if __name__ == "__main__":
    create_tables()

6 CRUD 增删改查完整示例

6.1 新增 Create

python 复制代码
from database import SessionLocal
from models import Department, Employee
from datetime import date

db = SessionLocal()
try:
    # 新增部门
    dept = Department(name="研发部", location="北京总部")
    db.add(dept)
    db.commit()
    db.refresh(dept) # 刷新获取自增id

    # 批量新增员工
    emp1 = Employee(name="张三", age=30, hire_date=date(2023,1,1), department_id=dept.id)
    emp2 = Employee(name="李四", age=28, hire_date=date(2023,3,15), department_id=dept.id)
    db.add_all([emp1, emp2])
    db.commit()
except Exception as e:
    db.rollback() # 异常回滚
finally:
    db.close()

6.2 查询 Read

python 复制代码
db = SessionLocal()
# 1.主键查询
dept = db.get(Department, 1)

# 2.条件过滤filter
emps = db.query(Employee).filter(Employee.department_id == 1).all()

# 3.多条件 and_ / or_
from sqlalchemy import and_, or_
emp = db.query(Employee).filter(and_(Employee.age>25, Employee.department_id==1)).first()

# 4.联表join查询
res = db.query(Employee, Department).join(Department, Employee.department_id == Department.id).all()

# 5.预加载关联数据,避免N+1查询
from sqlalchemy.orm import joinedload
emps = db.query(Employee).options(joinedload(Employee.department)).all()

6.3 更新 Update

python 复制代码
db = SessionLocal()
emp = db.query(Employee).filter(Employee.name == "张三").first()
if emp:
    emp.age = 31
    db.commit()

6.4 删除 Delete

python 复制代码
db = SessionLocal()
emp = db.query(Employee).filter(Employee.name == "李四").first()
if emp:
    db.delete(emp)
    db.commit()

7 表关联关系详解

7.1 一对多 / 多对一(最常用)

  • 子表添加外键ForeignKey
  • 主表relationship返回列表,子表反向返回单个对象
  • back_populates双向关联,代码可读性优于 backref

7.2 一对一

  1. 子表外键添加unique=True保证唯一
  2. 主表 relationship 添加uselist=False,返回单个对象而非列表

7.3 多对多(中间表 Table)

python 复制代码
from sqlalchemy import Table
# 中间表,无模型类
student_course = Table(
    "student_course",
    Base.metadata,
    Column("student_id", Integer, ForeignKey("students.id"), primary_key=True),
    Column("course_id", Integer, ForeignKey("courses.id"), primary_key=True)
)
# 模型中通过secondary绑定中间表
courses = relationship("Course", secondary=student_course, back_populates="students")

relationship 核心参数

  1. back_populates:双向关联(推荐)
  2. cascade:级联操作all, delete-orphan删除主表同步删子表
  3. lazy加载策略:selectin批量加载避免 N+1,joined联表加载

8 sqlacodegen 逆向生成模型(已有数据库自动生成类)

8.1 安装工具

bash 复制代码
pip install sqlacodegen pymysql

8.2 代码自动生成模型

python 复制代码
import subprocess, sys
DB_URL = "mysql+pymysql://root:123456@localhost:3306/fastapi_db"
cmd = [sys.executable, "-m", "sqlacodegen", DB_URL]
result = subprocess.run(cmd, capture_output=True, text=True)
# 输出写入table_2_models.py
with open("table_2_models.py", "w", encoding="utf8") as f:
    f.write(result.stdout)

适合遗留数据库项目,不用手动写模型字段

9 本章总结

  1. SQLAlchemy 三层架构:DBAPI→Core→ORM,Engine/Base/Session 三大核心
  2. CRUD 操作必须手动 commit,异常执行 rollback 事务回滚
  3. 表关联依靠外键 + relationship,合理配置 lazy 优化查询性能
  4. sqlacodegen 逆向生成模型,大幅节省已有数据库建模时间
相关推荐
ATMQuant7 小时前
以AI量化为生:25.vnpy 4.4升级实战 - 魔改版框架如何安全跟进上游
人工智能·python·量化交易·vnpy
卷无止境8 小时前
拯救乱码方块:pandas 绘图中文字体的一揽子解决方案
后端·python
李昊哲小课8 小时前
fastapi sse websocket 智能家居实时控制台
python·websocket·智能家居·fastapi·sse
杰佛史彦明 本王是暴君8 小时前
PyTorch KernelAgent 源码解读 ---(2)--- 总体流程
人工智能·pytorch·python
Zane19949 小时前
别再手写 try/finally 了:一文讲透 with 语句背后的上下文管理器协议
后端·python
李可以量化9 小时前
量化高性能服务框架 Tornado 全面解析(上):异步非阻塞的核心能力与场景落地
大数据·python·量化交易·tornado·qmt·ptrade
内蒙深海大鲨鱼9 小时前
3.Introduction to PyTorch YouTube Series--Autograd
人工智能·pytorch·python
用户0332126663679 小时前
使用 Python 在 Excel 中添加或删除批注
python·excel
dogstarhuang9 小时前
手把手用 Doubao-Seed-Evolving 写一个网站监控脚本:完整代码与两处踩坑
python·ai编程·掘金技术征文
ZZHow10249 小时前
PyTorch深度学习入门笔记(小土堆)P7-14
人工智能·pytorch·笔记·python·深度学习