AI项目博客
记录 AI 工程实践与大模型应用

FastAPI & SQLAlchemy 实战(八):SQLAlchemy 入门:ORM、Engine、Session 与建表

「FastAPI & SQLAlchemy 实战」系列共 10 篇,从协程基础讲到数据库接口。这是第 8 篇。

结论:SQLAlchemy 用三层完成数据库操作:Engine 管连接,Base 管表结构,Session 管一次会话里的增删改查。

一、ORM 是什么

ORM 把表映射成类、把行映射成对象:Department 类对应 departments 表,一个 Department 对象对应一行记录。好处是屏蔽数据库差异、少写 SQL、类型转换由框架处理。

SQLAlchemy 分两层:Core 提供 SQL 表达式、连接池、方言;ORM 在 Core 之上提供类和对象操作。FastAPI 项目通常直接用 ORM。

二、安装与建库

pip install sqlalchemy pymysql
# 先在 MySQL 建库
CREATE DATABASE fastapi_db CHARACTER SET utf8mb4;

三、Base:所有模型的父类

# base.py
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

SQLAlchemy 2.0 也可以用 class Base(DeclarativeBase): pass,效果一样;本篇沿用文档里的 declarative_base()。

四、模型:字段、外键、关系

# models.py
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"), nullable=False)

    department = relationship("Department", back_populates="employees", lazy="joined")

primary_key、nullable、unique 是列约束;ForeignKey 建外键;relationship 让对象可以直接互相访问。

五、Engine 与 Session

# database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "mysql+pymysql://root:123456@localhost:3306/fastapi_db"

engine = create_engine(
    DATABASE_URL,
    echo=True,           # 开发时打印 SQL,生产关掉
    pool_pre_ping=True,  # 取连接前先探活
)

SessionLocal = sessionmaker(
    bind=engine,
    autocommit=False,
    autoflush=False,
)

六、建表

# create_tables.py
from base import Base
from database import engine
import models  # 必须导入,否则模型没注册到 Base.metadata

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

if __name__ == "__main__":
    create_table()

create_all 只会建不存在的表,不会改已有表结构;生产环境改表要用迁移工具。

七、验证

python create_tables.py
# 在 MySQL 执行
SHOW TABLES;             # departments, employees
DESC employees;          # 字段、外键、索引

八、常见错误

  • 忘了导入模型:Base.metadata 里没有表,create_all 什么都不建;
  • 连接串驱动写错:mysql+pymysql:// 不能省;
  • 生产开 echo=True:SQL 日志刷屏;
  • 用 create_all 改表:它不会加字段,改结构要迁移。

下一篇

表和模型有了,下一篇写 CRUD:增删改查、关联关系、加载策略。

上一篇:请求体、Pydantic 与 APIRouter 路由拆分 | 下一篇:SQLAlchemy CRUD、关联关系与加载策略

赞(0)
未经允许不得转载:AI项目博客 » FastAPI & SQLAlchemy 实战(八):SQLAlchemy 入门:ORM、Engine、Session 与建表

评论 1

  1. #1

    我要看文章

    游客 重庆市 · IP 116.168.9.*6天前回复

AI项目博客

专注 AI 工程化落地 —— 覆盖智能体、大模型、Java AI 与 Python 的学习笔记,以及 AI 平台的项目实战记录。

关于本站文章归档

登录

找回密码

注册