Python中的ORM——SQLAlchemy

后端操作数据库

在后端开发中常常需要操作数据库进行增删改查,一共有三种操作数据库的方式

1. 原生 SQL(最底层)

直接写 SQL 语句,发给数据库执行。
连表结构定义都不用 ,数据库里有表就能操作,代码里只认表名字符串字段名字符串

2. DB Utils / Database Core(半封装)

不是 ORM,只是把 SQL 包装成方法 ,不用拼接字符串。

直接用 Table 对象定义表结构(也可动态生成)

比如:

  • Python:SQLAlchemy Core
  • Java:JdbcTemplate
  • Go:database/sql
优点
  • 比原生安全
  • 比 ORM 灵活
  • 适合复杂查询
示例(伪代码)
复制代码
select(table).where(user.c.id == 1)
3. ORM(最主流、最常用)

把数据库表 → 变成代码里的 "对象"

不用写 SQL,直接操作对象。

优点
  • 开发极快
  • 代码优雅
  • 防 SQL 注入
  • 跨数据库(换库不用改代码)
示例(伪代码)
复制代码
user = User.get(id=1)  # 自动生成 SQL

下面重点介绍ORM

全称 Object Relational Mapping (对象关系映射),是一种把数据库表映射成编程语言对象的技术,让你不用写原生 SQL,直接用面向对象方式操作数据库。

ORM 就是中间翻译官:

  • ↔ 数据库
  • 对象 ↔ 表中的一行数据
  • 对象属性 ↔ 表的字段

你只需要操作对象,ORM 自动帮你生成并执行 SQL。

在Python中FastAPI 框架在操作数据库时常用的ORM为SQLAlchemy


SQLAlchemy

SQLAlchemy 是 Python 生态最主流、功能最完善的 ORM 框架,分为两大核心部分:

  1. ORM(高层) :用类和对象操作数据库
  2. Core(底层):用 Python 语法写 SQL,灵活度极高

它支持 MySQL、PostgreSQL、SQLite、Oracle 等所有主流数据库。

核心概念(必须懂)
  1. Engine(引擎):数据库连接入口,管理连接池
  2. Base(基类):所有模型类都继承它
  3. Model(模型) :对应数据库
  4. Column(字段) :对应表的
  5. Session(会话):操作数据库的 "手柄",增删改查都靠它

进行数据库操作的常规流程

1. 第一步:创建引擎 + 基类 + Session(固定模板)

这是每个项目都一模一样的初始化代码

复制代码
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 1. 数据库连接 URL
# SQLite: "sqlite:///./test.db"
# MySQL:  "mysql+pymysql://user:password@localhost/dbname"
SQLALCHEMY_DATABASE_URL = "sqlite:///./mydb.db"

# 2. 创建引擎
engine = create_engine(
    SQLALCHEMY_DATABASE_URL,
    connect_args={"check_same_thread": False}  # SQLite 专用
)

# 3. 基类(所有模型都要继承它)
Base = declarative_base()

# 4. Session 工厂(用来和数据库会话)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

平时开发,这一段直接复制到 database.py

2. 第二步:写模型类(对应数据库表)

有几张表写几个类 ,类继承 Base

复制代码
from sqlalchemy import Column, Integer, String, DateTime
from datetime import datetime

class User(Base):
    __tablename__ = "users"  # 数据库表名

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50), nullable=False)
    email = Column(String(100), unique=True, index=True)
    age = Column(Integer)
    created_at = Column(DateTime, default=datetime.utcnow)
  • __tablename__:对应库里的表名
  • Column(类型, 选项):对应字段
  • 常用类型:IntegerString(n)DateTimeBooleanFloat
3. 第三步:建表(第一次运行用一次)
复制代码
# 放在主程序入口运行一次即可
Base.metadata.create_all(bind=engine)

执行后,数据库自动生成 users 表。

4. 第四步:获取 Session(操作数据库必须有)
复制代码
db = SessionLocal()

用完记得 db.close()

5. 日常 CRUD(最常用,背下来)
🔹 增(Create)
复制代码
user = User(name="张三", email="zhangsan@example.com", age=20)
db.add(user)
db.commit()

# 拿到自增 id
print(user.id)
🔹 查(Read)
复制代码
# 查所有
all_users = db.query(User).all()

# 按 id 查(单个)
user = db.query(User).get(1)

# 条件查询
user = db.query(User).filter_by(email="zhangsan@example.com").first()

# 模糊查询
users = db.query(User).filter(User.name.like("%张%")).all()

# 分页
users = db.query(User).offset(0).limit(10).all()
🔹 改(Update)
复制代码
user = db.query(User).get(1)
if user:
    user.age = 21
    db.commit()
🔹 删(Delete)
复制代码
user = db.query(User).get(1)
if user:
    db.delete(user)
    db.commit()
相关推荐
m0_613856291 小时前
C#怎么判断进程是否在运行_C#如何管理系统进程【必备】
jvm·数据库·python
NaMM CHIN2 小时前
MySQL无法连接到本地localhost的解决办法2024.11.8
数据库·mysql·adb
Irene19912 小时前
PL/SQL:变量使用 两个连续的外部输入 注意事项
数据库·sql
Jetev2 小时前
golang如何实现审计日志记录_golang审计日志记录实现教程
jvm·数据库·python
yexuhgu2 小时前
Redis如何解决哨兵通知延迟问题_优化客户端连接池动态刷新拓扑的订阅监听机制
jvm·数据库·python
洛水水2 小时前
Redis 协议与异步通信深度解析
数据库·redis·缓存
S1998_1997111609•X13 小时前
论当今社会主义与人文关怀人格思想下的恶意仿生注入污染蜜罐描述进行函数值非法侵入爬虫的咼忄乂癿〇仺⺋.
数据库·网络协议·百度·ssh·开闭原则
倔强的石头_14 小时前
kingbase备份与恢复实战(六)—— 备份自动化与保留策略:Windows任务计划+日志追溯
数据库
轻刀快马15 小时前
别被 ORM 框架宠坏了:从一场“订单消失”悬案,看懂 MySQL 为什么要强推 InnoDB
数据库·mysql