


1. 认识SQLAlchemy
SQLAlchemy是Python SQL工具包和对象关系映射器。它专为高校和高性能的数据库访问而设计。它支持连接SQLite、PostgreSQL、Oracle、MySQL/MariaDB、Microsoft SQL Server等等。
它提供了两种主要的使用模式:
SQLAlchemy Core,通过Table构造函数初始化Table对象。
ORM,通过定义一个类,继承declarative_base这个特殊基类(SQLAlchemy 2.0j继承的是DeclarativeBase,注意看官方文档),declarative_base会把元数据容器(类)和映射器(数据表)结合在一起。
目前官方SQLAlchemy最新版本为2.0.0。
无论使用哪种方式,都需要连接到数据库。需要创建一个SQLAlchemy引擎,创建引擎如下:
from sqlalchemy import create_engine
# SQLite连接
engine = create_engine("sqlite:///:memory:", echo=True, future=True)
engine = create_engine("sqlite:///relative/path/to/file.db", echo=True, future=True)
engine = create_engine("sqlite:////absolute/path/to/file.db", echo=True, future=True)
2. 使用ORM
以下例子使用SQLAlchemy 1.4.32实验,其他版本参考官方文档。
orm使用的类应该满足如下要求:
继承自declarative_base对象
包含__tablename__,数据库表名称
包含一个或多个属性,它们都是Column对象
确保一个或多个属性组成主键
2.1 声明模块
每个表都被定义为一个模块,在项目中只需要声明一次,它包含了数据库表的信息,比如表名称、列名称、列属性等元数据。
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import declarative_base, relationship
Base = declarative_base()
class User(Base):
__tablename__ = "user_account"
id = Column(Integer, primary_key=True)
name = Column(String(30))
fullname = Column(String)
addresses = relationship("Address", back_populates="user", cascade="all, delete-orphan")
def __repr__(self):
return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"
class Address(Base):
__tablename__ = "address"
id = Column(Integer, primary_key=True)
email_address = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey("user_account.id"), nullable=False)
user = relationship("User", back_populates="addresses")
def __repr__(self):
return f"Address(id={self.id!r}, email_address={self.email_address!r})" relationship()表示在两个ORM类之间进行联动,比如User的addresses属性关联到Address,Address的user属性关联到User,更深层的用法待补充。
2.2 创建引擎
引擎能为我们创建新的数据库连接,它是维持在连接池里的,方便复用。
from sqlalchemy import create_engine
# 创建引擎连接
engine = create_engine("sqlite:///test.sqlite", echo=True, future=True)
# 创建表
Base.metadata.create_all(engine) echo=True,会将表创建语句记录在标准输出里。程序会自动创建test.sqlite数据库文件。
运行日志如下:

2.3 插入数据
创建的模块实例如果要持久化到数据库中,需要调用会话Session,Session会和数据库进行交互,它封装了一个事务,这个事务将一直保持打开状态,直到会话提交或回滚。看下方例子:
# 插入数据
with Session(engine) as session:
xiaoming = User(
name="xiaoming",
fullname="Zhang Xiaoming",
addresses=[Address(email_address='xiaoming@qq.com')]
)
xiaowu = User(
name="xiaowu",
fullname="Zhang Xiaowu"
)
xiaoliu = User(
name="xiaoliu",
fullname="Zhang Xiaoliu",
addresses=[Address(email_address='xiaoliu@qq.com'),
Address(email_address='xiaoliu@ww.com')]
)
# 将实例添加到表里
session.add_all([xiaowu, xiaoliu, xiaoming])
# 提交事务,刷新到数据库中
session.commit() session.add_all可以一次性添加多个对象实例。
session.add一次添加一个实例。
从日志看就是提交了一个事务,从数据库表里看用户表和地址表数据都插入成功了,

2.4 查询数据
2.4.1 单表查询
查询数据使用到sqlalchemy的select方法,where中指明条件,session.scalars会返回一个可迭代对象ScalarResult。
from sqlalchemy import select
# 查询数据
with Session(engine) as session:
result = select(User).where(User.name.in_(["xiaowu", "xiaoliu"]))
for user in session.scalars(result):
print(user) 下方为查询语句和查询结果:

2.4.2 多表查询
查询xiaoliu的地址信息
# join查询
result = select(Address).join(Address.user).where(User.name=='xiaoliu').\
where(Address.email_address == 'xiaoliu@qq.com')
with Session(engine) as session:
s = session.scalars(result).one()
print(s) 查询结果:

2.5 更新数据
例子:
把xiaowu的全名修改为Zhang Xiaowu Hahaha,地址追加"xiaowu@ll.com"
# 更新数据
stmt = select(User).where(User.name == "xiaowu")
with Session(engine) as session:
xiaowu_info = session.scalars(stmt).one()
xiaowu_info.addresses.append(Address(email_address="xiaowu@ll.com"))
xiaowu_info.fullname = "Zhang Xiaowu Hahaha"
session.commit() 运行结果:

2.6 删除数据
例子:删除xiaowu的账号和地址信息
# 删除数据
with Session(engine) as session:
# 获取xiaowu的账户信息
xiaowu = session.get(User, 1)
session.delete(xiaowu)
session.commit() 运行结果:xiaowu的账号信息和地址信息均删除。

3. 参考资料
SQLAlchemy官方文档:https://www.sqlalchemy.org/
Python库之SQLAlchemy: https://zhuanlan.zhihu.com/p/265224273