Python数据库操作:SQLAlchemy ORM指南

SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式。本文将介绍如何使用SQLAlchemy ORM进行数据库操作。

目录

  1. 安装SQLAlchemy

  2. 核心概念

  3. 连接数据库

  4. 定义数据模型

  5. 创建数据库表

  6. 基本CRUD操作

  7. 查询数据

  8. 关系操作

  9. 事务管理

  10. 最佳实践

安装

bash

复制代码
pip install sqlalchemy

如果需要连接特定数据库,还需安装相应的驱动程序:

bash

复制代码
# PostgreSQL
pip install psycopg2-binary

# MySQL
pip install mysql-connector-python

# SQLite (Python标准库已包含,无需额外安装)

核心概念

  • Engine:数据库连接的引擎,负责与数据库通信

  • Session:数据库会话,管理所有持久化操作

  • Model:数据模型类,对应数据库中的表

  • Query:查询对象,用于构建和执行数据库查询

连接数据库

python

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

# 创建数据库连接引擎
# SQLite示例
engine = create_engine('sqlite:///example.db', echo=True)

# PostgreSQL示例
# engine = create_engine('postgresql://username:password@localhost:5432/mydatabase')

# MySQL示例
# engine = create_engine('mysql+mysqlconnector://username:password@localhost:3306/mydatabase')

# 创建会话工厂
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# 创建会话实例
session = SessionLocal()

定义数据模型

python

复制代码
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, declarative_base

# 创建基类
Base = declarative_base()

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)
    
    # 定义一对多关系
    posts = relationship("Post", back_populates="author")
    
class Post(Base):
    __tablename__ = 'posts'
    
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(100), nullable=False)
    content = Column(String(500))
    author_id = Column(Integer, ForeignKey('users.id'))
    
    # 定义多对一关系
    author = relationship("User", back_populates="posts")
    
    # 定义多对多关系(通过关联表)
    tags = relationship("Tag", secondary="post_tags", back_populates="posts")

class Tag(Base):
    __tablename__ = 'tags'
    
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(30), unique=True, nullable=False)
    
    posts = relationship("Post", secondary="post_tags", back_populates="tags")

# 关联表(用于多对多关系)
class PostTag(Base):
    __tablename__ = 'post_tags'
    
    post_id = Column(Integer, ForeignKey('posts.id'), primary_key=True)
    tag_id = Column(Integer, ForeignKey('tags.id'), primary_key=True)

创建数据库表

python

复制代码
# 创建所有表
Base.metadata.create_all(bind=engine)

# 删除所有表
# Base.metadata.drop_all(bind=engine)

基本CRUD操作

创建数据

python

复制代码
# 创建新用户
new_user = User(name="张三", email="zhangsan@example.com")
session.add(new_user)
session.commit()

# 批量创建
session.add_all([
    User(name="李四", email="lisi@example.com"),
    User(name="王五", email="wangwu@example.com")
])
session.commit()

读取数据

python

复制代码
# 获取所有用户
users = session.query(User).all()

# 获取第一个用户
first_user = session.query(User).first()

# 根据ID获取用户
user = session.query(User).get(1)

更新数据

python

复制代码
# 查询并更新
user = session.query(User).get(1)
user.name = "张三四"
session.commit()

# 批量更新
session.query(User).filter(User.name.like("张%")).update({"name": "张氏"}, synchronize_session=False)
session.commit()

删除数据

python

复制代码
# 查询并删除
user = session.query(User).get(1)
session.delete(user)
session.commit()

# 批量删除
session.query(User).filter(User.name == "李四").delete(synchronize_session=False)
session.commit()

查询数据

基本查询

python

复制代码
# 获取所有记录
users = session.query(User).all()

# 获取特定字段
names = session.query(User.name).all()

# 排序
users = session.query(User).order_by(User.name.desc()).all()

# 限制结果数量
users = session.query(User).limit(10).all()

# 偏移量
users = session.query(User).offset(5).limit(10).all()

过滤查询

python

复制代码
from sqlalchemy import or_

# 等值过滤
user = session.query(User).filter(User.name == "张三").first()

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

# IN查询
users = session.query(User).filter(User.name.in_(["张三", "李四"])).all()

# 多条件查询
users = session.query(User).filter(
    User.name == "张三", 
    User.email.like("%@example.com")
).all()

# 或条件
users = session.query(User).filter(
    or_(User.name == "张三", User.name == "李四")
).all()

# 不等于
users = session.query(User).filter(User.name != "张三").all()

聚合查询

python

复制代码
from sqlalchemy import func

# 计数
count = session.query(User).count()

# 分组计数
user_post_count = session.query(
    User.name, 
    func.count(Post.id)
).join(Post).group_by(User.name).all()

# 求和、平均值等
avg_id = session.query(func.avg(User.id)).scalar()

连接查询

python

复制代码
# 内连接
results = session.query(User, Post).join(Post).filter(Post.title.like("%Python%")).all()

# 左外连接
results = session.query(User, Post).outerjoin(Post).all()

# 指定连接条件
results = session.query(User, Post).join(Post, User.id == Post.author_id).all()

关系操作

python

复制代码
# 创建带关系的对象
user = User(name="赵六", email="zhaoliu@example.com")
post = Post(title="我的第一篇博客", content="Hello World!", author=user)
session.add(post)
session.commit()

# 通过关系访问
print(f"文章 '{post.title}' 的作者是 {post.author.name}")
print(f"用户 {user.name} 的所有文章:")
for p in user.posts:
    print(f"  - {p.title}")

# 多对多关系操作
python_tag = Tag(name="Python")
sqlalchemy_tag = Tag(name="SQLAlchemy")

post.tags.append(python_tag)
post.tags.append(sqlalchemy_tag)
session.commit()

print(f"文章 '{post.title}' 的标签:")
for tag in post.tags:
    print(f"  - {tag.name}")

事务管理

python

复制代码
# 自动提交事务
try:
    user = User(name="测试用户", email="test@example.com")
    session.add(user)
    session.commit()
except Exception as e:
    session.rollback()
    print(f"发生错误: {e}")

# 使用事务上下文管理器
from sqlalchemy.orm import Session

def create_user(session: Session, name: str, email: str):
    try:
        user = User(name=name, email=email)
        session.add(user)
        session.commit()
        return user
    except:
        session.rollback()
        raise

# 嵌套事务
with session.begin_nested():
    user = User(name="事务用户", email="transaction@example.com")
    session.add(user)

# 保存点
savepoint = session.begin_nested()
try:
    user = User(name="保存点用户", email="savepoint@example.com")
    session.add(user)
    savepoint.commit()
except:
    savepoint.rollback()

最佳实践

  1. 会话管理:为每个请求创建新会话,请求结束后关闭

  2. 异常处理:始终处理异常并适当回滚事务

  3. 延迟加载:注意N+1查询问题,使用 eager loading 优化

  4. 连接池:合理配置连接池大小和超时设置

  5. 数据验证:在模型层或应用层验证数据完整性

python

复制代码
# 使用上下文管理器管理会话
from contextlib import contextmanager

@contextmanager
def get_db():
    db = SessionLocal()
    try:
        yield db
        db.commit()
    except Exception:
        db.rollback()
        raise
    finally:
        db.close()

# 使用示例
with get_db() as db:
    user = User(name="上下文用户", email="context@example.com")
    db.add(user)

总结

SQLAlchemy ORM提供了强大而灵活的数据库操作方式,通过本文的介绍,您应该能够:

  1. 安装和配置SQLAlchemy

  2. 定义数据模型和关系

  3. 执行基本的CRUD操作

  4. 构建复杂查询

  5. 管理数据库事务

  6. 遵循最佳实践

SQLAlchemy还有更多高级特性,如混合属性、事件监听、自定义查询等,值得进一步探索学习。

相关推荐
YOU OU5 小时前
Redis基础常识与命令
数据库·redis·缓存
Scott9999HH5 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
AI云海6 小时前
python 列表、元组、集合和字典
开发语言·python
二十雨辰7 小时前
[爬虫]-Urllib
爬虫·python
Database_Cool_7 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
爱写代码的阿森8 小时前
鸿蒙三方库 | harmony-utils之KvUtil键值型数据库操作详解
数据库·华为·harmonyos·鸿蒙·huawei
Database_Cool_8 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
玉鸯8 小时前
Agent Hook:在概率推理之上,为 Agent 叠加确定性控制
python·langchain·agent
姜太小白9 小时前
【MySQL】 索引优化实战:解决 WHERE 等值 + IS NULL 查询,TEXT 字段报错 1167 的完整指南
数据库·mysql