当前位置:首页 > 技术 > 正文内容

使用Python高效管理数据库:从零构建ORM应用

访客 技术 2026年7月22日 3

快速上手SQLAlchemy:Python中的数据库抽象层

SQLAlchemy 是 Python 生态中广泛使用的对象关系映射(ORM)工具,它将数据库表与类模型对应,使数据操作更加直观和安全。本文将以实战方式介绍如何利用 SQLAlchemy 构建可维护的数据库交互逻辑。

环境准备 安装核心库及对应数据库驱动:

pip install sqlalchemy
# 选择性安装:
pip install psycopg2-binary    # PostgreSQL
pip install mysql-connector-python  # MySQL

关键组件解析

  • Engine:数据库连接的入口,负责建立与底层数据库的通信。
  • Session:会话对象,用于执行增删改查操作并管理事务。
  • Declarative Base:所有数据模型的基类,定义表结构和字段映射。
  • Query:提供链式方法构建复杂查询条件。

数据库连接配置

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 连接本地 SQLite 数据库
engine = create_engine("sqlite:///app_data.db", echo=True)

# 或连接远程数据库(示例为 PostgreSQL)
# engine = create_engine("postgresql://user:pass@localhost:5432/myapp")

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

定义数据实体

from sqlalchemy import Column, Integer, String, ForeignKey, DateTime
from sqlalchemy.orm import relationship, declarative_base
from datetime import datetime

Base = declarative_base()

class Author(Base):
    __tablename__ = 'authors'

    id = Column(Integer, primary_key=True, index=True)
    full_name = Column(String(80), nullable=False)
    email = Column(String(120), unique=True, index=True)
    created_at = Column(DateTime, default=datetime.utcnow)

    # 一对多关系:作者拥有多篇文章
    articles = relationship("Article", back_populates="author", cascade="all, delete-orphan")

class Article(Base):
    __tablename__ = 'articles'

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(200), nullable=False)
    body = Column(String(2000))
    published_at = Column(DateTime, default=datetime.utcnow)
    author_id = Column(Integer, ForeignKey('authors.id'), nullable=False)

    # 多对一关系:文章属于某个作者
    author = relationship("Author", back_populates="articles")

    # 关联标签(多对多)
    tags = relationship(
        "Tag",
        secondary="article_tags",
        back_populates="articles"
    )

class Tag(Base):
    __tablename__ = 'tags'

    id = Column(Integer, primary_key=True, index=True)
    label = Column(String(50), unique=True, nullable=False)

    articles = relationship(
        "Article",
        secondary="article_tags",
        back_populates="tags"
    )

# 多对多关联表
class ArticleTag(Base):
    __tablename__ = 'article_tags'

    article_id = Column(Integer, ForeignKey('articles.id'), primary_key=True)
    tag_id = Column(Integer, ForeignKey('tags.id'), primary_key=True)

初始化数据库表结构

# 创建所有表
Base.metadata.create_all(bind=engine)

# 清空所有表(仅开发时使用)
# Base.metadata.drop_all(bind=engine)

典型数据操作流程

插入数据

db_session = SessionLocal()

# 单条插入
new_author = Author(full_name="林晓", email="linxiao@example.com")
db_session.add(new_author)
db_session.commit()

# 批量插入
db_session.add_all([
    Author(full_name="陈晨", email="chenchen@example.com"),
    Author(full_name="周涛", email="zhtao@example.com")
])
db_session.commit()

查询数据

# 获取全部记录
all_authors = db_session.query(Author).all()

# 条件筛选
published_articles = db_session.query(Article)\
    .filter(Article.published_at.isnot(None))\
    .order_by(Article.published_at.desc())\
    .limit(5).all()

# 模糊匹配
search_results = db_session.query(Author)\
    .filter(Author.full_name.like("%林%"))\
    .all()

更新与删除

# 单个更新
author = db_session.query(Author).get(1)
if author:
    author.email = "newemail@example.com"
    db_session.commit()

# 批量更新
db_session.query(Article)\
    .filter(Article.title.ilike("%初学%"))\
    .update({"published_at": datetime.utcnow()}, synchronize_session=False)
db_session.commit()

# 删除
db_session.query(Author).filter(Author.id == 1).delete(synchronize_session=False)
db_session.commit()

高级查询技巧

from sqlalchemy import func, or_

# 统计总数
total_authors = db_session.query(Author).count()

# 分组聚合
author_article_count = db_session.query(
    Author.full_name,
    func.count(Article.id)
).join(Article).group_by(Author.full_name).all()

# 联合查询
results = db_session.query(Author, Article)\
    .join(Article, Author.id == Article.author_id)\
    .filter(Article.title.contains("Python"))\
    .all()

处理复杂关系

# 建立带关联的数据
author = db_session.query(Author).first()
article = Article(title="Python ORM 实践", body="深入探讨...", author=author)
db_session.add(article)
db_session.commit()

# 通过关系访问相关数据
print(f"文章《{article.title}》由 {article.author.full_name} 发布")

# 多对多标签管理
py_tag = db_session.query(Tag).filter(Tag.label == "Python").first()
if not py_tag:
    py_tag = Tag(label="Python")
    db_session.add(py_tag)

article.tags.append(py_tag)
db_session.commit()

事务控制策略

# 使用上下文管理器确保资源释放
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 db:
    new_article = Article(title="测试文章", author=db.query(Author).first())
    db.add(new_article)

推荐开发规范

  • 为每个请求创建独立会话,避免跨请求共享状态。
  • 使用 try-except 包裹数据库操作,确保异常时自动回滚。
  • 对于包含子集的查询,优先使用 joinedload 避免 N+1 查询问题。
  • 合理设置连接池参数,如最大连接数、超时时间等。
  • 在模型中添加数据校验逻辑或使用验证库增强安全性。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。