python中sqlalchemy的全面学习:增删改查与表关联应用详解
引言
sqlalchemy 是 python 中最流行的 orm(对象关系映射)工具之一,它使得开发者能够以面向对象的方式操作数据库,极大地提高了开发效率和代码可读性。本文将详细介绍如何使用 sqlalchemy 实现数据库的增删改查(crud)操作,以及如何处理表之间的关联关系。
1. 环境准备
安装 sqlalchemy
pip install sqlalchemy
导入必要的模块
from sqlalchemy import create_engine, column, integer, string, foreignkey, datetime, text from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship import datetime
2. 创建数据库引擎和会话工厂
# 创建数据库引擎,这里以 sqlite 为例(也可以使用 mysql、postgresql 等)
engine = create_engine('sqlite:///example.db', echo=true) # echo=true 用于显示 sql 语句
# 创建基类(所有模型类的基类)
base = declarative_base()
# 创建会话工厂(用于创建会话对象)
sessionlocal = sessionmaker(bind=engine)3. 定义数据模型(表结构)
3.1 定义用户表(user)
class user(base):
__tablename__ = 'users'
id = column(integer, primary_key=true)
username = column(string(50), nullable=false, unique=true)
email = column(string(100), nullable=false)
created_at = column(datetime, default=datetime.datetime.utcnow)
# 定义与文章表的关联关系(反向关系)
posts = relationship("post", back_populates="author")
def __repr__(self):
return f"<user(id={self.id}, username='{self.username}', email='{self.email}')>"3.2 定义文章表(post)
class post(base):
__tablename__ = 'posts'
id = column(integer, primary_key=true)
title = column(string(100), nullable=false)
content = column(string(1000))
created_at = column(datetime, default=datetime.datetime.utcnow)
user_id = column(integer, foreignkey('users.id')) # 外键关联到 user 表
# 定义与用户表的关联关系(正向关系)
author = relationship("user", back_populates="posts")
def __repr__(self):
return f"<post(id={self.id}, title='{self.title}', user_id={self.user_id})>"4. 创建数据库表
# 通过 base.metadata.create_all() 创建所有定义的表 base.metadata.create_all(engine)
5. 执行 crud 操作(增删改查)
5.1 增加(create)
# 创建会话实例
session = sessionlocal()
try:
# 创建新用户
new_user = user(username='alice', email='alice@example.com')
session.add(new_user)
session.commit() # 提交事务,保存到数据库
print(f"用户 {new_user.username} 添加成功!")
# 创建新文章,关联到用户
new_post = post(title='我的第一篇博客', content='这是我的第一篇文章内容。', user_id=new_user.id)
session.add(new_post)
session.commit()
print(f"文章 {new_post.title} 添加成功!")
except exception as e:
session.rollback() # 出错时回滚事务
print(f"添加失败:{e}")
finally:
session.close()5.2 查询(read)
5.2.1 按主键查询单个记录
session = sessionlocal()
try:
user = session.query(user).filter(user.id == 1).first()
if user:
print(user)
else:
print("未找到该用户")
finally:
session.close()5.2.2 条件查询多个记录
session = sessionlocal()
try:
users = session.query(user).filter(user.username.like('%a%')).all()
for user in users:
print(user)
finally:
session.close()5.2.3 使用 join 进行多表联合查询(关联查询)
session = sessionlocal()
try:
# 查询所有用户的姓名及其发表的文章标题
results = session.query(user.username, post.title).join(post).all()
for username, title in results:
print(f"{username} - {title}")
finally:
session.close()5.2.4 使用with_parent查询关联数据(更简洁的方式)
session = sessionlocal()
try:
# 获取用户 alice 及其所有文章
alice = session.query(user).filter(user.username == 'alice').first()
if alice:
for post in alice.posts:
print(post.title)
finally:
session.close()
5.3 修改(update)
session = sessionlocal()
try:
# 更新用户邮箱
user = session.query(user).filter(user.username == 'alice').first()
if user:
user.email = 'alice_new@example.com'
session.commit()
print(f"用户 {user.username} 的邮箱已更新为 {user.email}")
else:
print("用户不存在")
except exception as e:
session.rollback()
print(f"更新失败:{e}")
finally:
session.close()5.4 删除(delete)
session = sessionlocal()
try:
# 删除文章,先删除文章再删除用户(注意外键约束)
post = session.query(post).filter(post.title == '我的第一篇博客').first()
if post:
session.delete(post)
session.commit()
print(f"文章 {post.title} 已删除")
else:
print("文章不存在")
except exception as e:
session.rollback()
print(f"删除失败:{e}")
finally:
session.close()6. 表之间关联的应用详解
6.1 一对一(one-to-one)
# 例如:用户有一个唯一的个人资料卡片(profile)
class profile(base):
__tablename__ = 'profiles'
id = column(integer, primary_key=true)
bio = column(string(500))
user_id = column(integer, foreignkey('users.id'), unique=true) # 一对一,外键唯一
user = relationship("user", backref="profile")6.2 一对多(one-to-many)
# 已在 user 和 post 之间实现:一个用户可以有多个文章(一对多) # 通过 `relationship` 和 `back_populates` 实现双向关系。
6.3 多对多(many-to-many)
# 例如:用户和标签之间是多对多关系(一个用户可以有多个标签,一个标签可以被多个用户使用)
# 创建中间表(关联表)
user_tag = table('user_tag', base.metadata,
column('user_id', integer, foreignkey('users.id')),
column('tag_id', integer, foreignkey('tags.id'))
)
class tag(base):
__tablename__ = 'tags'
id = column(integer, primary_key=true)
name = column(string(50), unique=true)
# 与用户的关系(多对多)
users = relationship("user", secondary=user_tag, back_populates="tags")
class user(base):
__tablename__ = 'users'
id = column(integer, primary_key=true)
username = column(string(50), nullable=false)
email = column(string(100), nullable=false)
# 与标签的关系(多对多)
tags = relationship("tag", secondary=user_tag, back_populates="users")6.3.1 使用多对多关系示例:添加标签
session = sessionlocal()
try:
# 创建用户和标签
user = user(username='bob')
tag1 = tag(name='python')
tag2 = tag(name='web')
# 将标签添加到用户(自动创建中间表记录)
user.tags.append(tag1)
user.tags.append(tag2)
session.add(user)
session.commit()
print(f"用户 {user.username} 已添加标签: {[t.name for t in user.tags]}")
except exception as e:
session.rollback()
print(f"添加标签失败:{e}")
finally:
session.close()7. 高级技巧与最佳实践
7.1 事务管理(transaction management)
session = sessionlocal()
try:
# 多个操作在一个事务中执行,保证一致性
user = user(username='charlie', email='charlie@example.com')
post = post(title='测试文章', content='测试内容', user_id=user.id)
session.add(user)
session.add(post)
session.commit() # 一次性提交,如果出错则回滚
except exception as e:
session.rollback()
print(f"事务失败:{e}")
finally:
session.close()7.2 优雅地关闭会话(使用上下文管理器)
from contextlib import contextmanager
@contextmanager
def get_db_session():
session = sessionlocal()
try:
yield session
session.commit()
except exception as e:
session.rollback()
raise e
finally:
session.close()
# 使用示例:
with get_db_session() as session:
user = user(username='david', email='david@example.com')
session.add(user)
# 无需手动调用 commit(),上下文管理器会自动处理7.3 使用query的链式调用进行复杂查询
# 查询用户名包含 'a' 且文章数量大于 1 的用户
results = (session.query(user)
.join(post)
.group_by(user.id)
.having(text("count(post.id) > 1"))
.filter(user.username.like('%a%'))
.all())
for user in results:
print(f"{user.username} 有 {len(user.posts)} 篇文章")总结
sqlalchemy 提供了强大而灵活的 orm 功能,使我们能够以简洁、直观的方式进行数据库操作。本文系统地介绍了:
- 如何定义模型类并创建数据库表;
- 如何执行基本的 crud 操作;
- 如何处理一对一、一对多、多对多等复杂的表关联关系;
- 一些高级技巧,如事务管理、上下文管理器、复杂查询等。
掌握这些知识后,你将能够在实际项目中高效地使用 sqlalchemy 操控数据库,提升开发效率和代码质量。
到此这篇关于python中sqlalchemy增删改查与表关联应用详解(最新推荐)的文章就介绍到这了,更多相关python sqlalchemy增删改查内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论