解析 Python Web 开发中的数据库与 ORM 技术
目录
- 🗂 数据库基础
- 关系型数据库 vs NoSQL 数据库
- ⚙️ SQLAlchemy
- ORM vs 原生 SQL
- SQLAlchemy 基础(Session、Model、Query 等)
- 关联查询、懒加载与急加载
- 事务处理和回滚
- 🛠 Django ORM
- Django ORM 的查询优化
- 自定义 Manager 和 QuerySet
- 数据库迁移(Django Migrations)
- ⏩ 异步数据库操作
- 使用 databases 库处理异步数据库连接
- 使用 Tortoise-ORM 实现异步 ORM 操作
1. 🗂 数据库基础
数据库是存储和管理数据的关键技术,分为关系型数据库和 NoSQL 数据库。关系型数据库通过表格来存储数据,遵循严格的模式约束和 ACID 特性;NoSQL 数据库则更加灵活,通常用于处理大规模和非结构化数据。
关系型数据库 vs NoSQL 数据库
关系型数据库(如 MySQL、PostgreSQL、SQLite)基于关系模型来组织数据,通常由多个表格组成,表格通过外键相互关联。它们提供了强大的查询语言(SQL),支持事务操作、数据一致性和复杂的查询优化。
-- 创建用户表的 SQL 语句
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);
关系型数据库最适合结构化的数据和复杂查询。其优点包括数据一致性、高度的 ACID 支持和丰富的查询功能。缺点在于需要事先定义模式,并且对水平扩展支持不如 NoSQL 数据库。
NoSQL 数据库(如 MongoDB、Redis、Cassandra)提供了非结构化或半结构化的数据存储,通常以键值对、文档或图形结构进行组织。这类数据库不强制使用固定的模式,因此在处理动态或大规模数据时表现更好。
{
"username": "john_doe",
"email": "john@example.com",
"hobbies": ["reading", "hiking"]
}
NoSQL 数据库的优点包括灵活的模式、横向扩展能力和对海量数据的处理。然而,由于缺乏一致性保障和事务支持,它们在某些应用场景中并不适用。
2. ⚙️ SQLAlchemy
SQLAlchemy 是 Python 最流行的 ORM(对象关系映射)框架之一,它为开发者提供了在 Python 代码中操作数据库的强大工具,允许在关系型数据库和对象之间无缝转换。
ORM vs 原生 SQL
ORM(对象关系映射) 提供了一种将数据库表映射为 Python 类的方式,开发者可以通过操作类对象来对数据库进行查询、插入和更新操作,而无需编写 SQL 语句。ORM 简化了数据库操作,并且在处理复杂关联时,能更好地提升开发效率。
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# 定义 ORM 模型
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(50), nullable=False)
email = Column(String(100), nullable=False, unique=True)
相比之下,原生 SQL 具有更高的灵活性和性能优势,尤其在复杂查询和优化场景中,开发者可以手动编写高度优化的 SQL 语句。ORM 在封装操作的同时,也可能导致一些性能上的开销。
SQLAlchemy 基础(Session、Model、Query 等)
在 SQLAlchemy 中,所有的数据库操作都围绕着 Session 对象展开,它是与数据库的会话接口,负责提交事务、执行查询并管理对象的生命周期。
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# 创建数据库引擎
engine = create_engine('sqlite:///app.db')
Session = sessionmaker(bind=engine)
# 创建会话
session = Session()
# 查询数据库
users = session.query(User).all()
for user in users:
print(user.username)
SQLAlchemy 的 Model 是数据库表的 Python 映射,开发者可以通过定义类属性来创建数据库列。Query 对象用于生成 SQL 查询,并且支持链式调用,构建复杂查询条件。
# 查询带有条件的用户
active_users = session.query(User).filter(User.active == True).all()
关联查询、懒加载与急加载
关联查询 用于从多个表中提取相关数据。SQLAlchemy 通过 relationship
提供了外键关联,使得开发者可以轻松处理一对多、多对多等关联查询。
from sqlalchemy.orm import relationship
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
title = Column(String(100), nullable=False)
user_id = Column(Integer, ForeignKey('users.id'))
# 定义关联关系
user = relationship("User", back_populates="posts")
SQLAlchemy 支持 懒加载 和 急加载,懒加载只在访问关联对象时才加载相关数据,而急加载则通过 join
一次性加载全部相关数据。
# 懒加载
user = session.query(User).get(1)
# 访问 posts 属性时才会查询关联的 Post 表
print(user.posts)
# 急加载
user = session.query(User).options(joinedload(User.posts)).get(1)
print(user.posts)
事务处理和回滚
事务是数据库操作的基本单位,SQLAlchemy 支持自动事务处理。通过 commit
提交事务,rollback
则用于回滚未完成的操作,确保数据的一致性。
try:
new_user = User(username='jane_doe', email='jane@example.com')
session.add(new_user)
session.commit() # 提交事务
except Exception as e:
session.rollback() # 出错时回滚
print(f"Error: {e}")
finally:
session.close()
事务处理机制确保了在操作失败时,数据库能够保持一致的状态,防止部分数据更新或异常数据写入。
3. 🛠 Django ORM
Django ORM 是 Django 框架自带的对象关系映射工具,它通过 Python 类与数据库表之间的映射,允许开发者以对象的方式进行数据库操作,极大简化了 SQL 的编写。
Django ORM 的查询优化
Django ORM 提供了许多内置的查询优化工具。开发者可以通过 select_related
和 prefetch_related
来优化关联查询,避免 N+1 查询问题。
# select_related: 用于一对一和多对一关联
posts = Post.objects.select_related('user').all()
# prefetch_related: 用于多对多和反向关联
posts = Post.objects.prefetch_related('comments').all()
通过这些方法,Django 可以在一次查询中加载关联的数据,减少数据库查询的次数,从而提高性能。
自定义 Manager 和 QuerySet
Django ORM 允许开发者通过自定义 Manager 和 QuerySet 来扩展默认的查询方法。Manager 是数据库模型的接口,可以通过自定义 Manager 来添加新的查询逻辑。
class ActiveUserManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_active=True)
class User(models.Model):
username = models.CharField(max_length=100)
is_active = models.BooleanField(default=True)
# 使用自定义 Manager
objects = ActiveUserManager()
自定义 QuerySet 则可以提供链式调用的方法,用于构建复杂的查询逻辑。
class UserQuerySet(models.QuerySet):
def active(self):
return self.filter(is_active=True)
class User(models.Model):
username = models.CharField(max_length=100)
# 绑定自定义 QuerySet
objects = UserQuerySet.as_manager()
数据库迁移(Django Migrations)
Django 的 Migrations 系统提供了一种简单的方式来管理数据库模式的变更。开发者可以通过命令自动生成迁移脚本,并执行迁移操作。
python manage.py makemigrations
python manage.py migrate
Migrations 使得在项目开发过程中,数据库结构的变化能够被轻松地跟踪和管理。
4. ⏩ 异步数据库操作
随着 Web 应用对高并发的需求不断增加,异步
数据库操作变得越来越重要。在 Python 中,databases
库和 Tortoise-ORM
是处理异步数据库操作的两大主流工具。
使用 databases 库处理异步数据库连接
databases
是一个专门用于异步数据库访问的库,它支持主流的数据库引擎,并且可以与 FastAPI 等异步框架无缝集成。
import databases
import sqlalchemy
# 定义数据库 URL
DATABASE_URL = "sqlite:///./test.db"
# 初始化数据库连接
database = databases.Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()
# 定义表
users = sqlalchemy.Table(
"users", metadata,
sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
sqlalchemy.Column("name", sqlalchemy.String, nullable=False)
)
# 异步数据库操作
async def fetch_users():
query = users.select()
return await database.fetch_all(query)
databases
库提供了简单易用的 API,使得异步数据库操作像同步操作一样直观。
使用 Tortoise-ORM 实现异步 ORM 操作
Tortoise-ORM 是一个轻量级的异步 ORM,支持多种数据库引擎,包括 PostgreSQL、MySQL 和 SQLite。它采用了 Django ORM 的设计风格,但支持异步操作,适用于高并发场景。
from tortoise import Tortoise, fields
from tortoise.models import Model
# 定义模型
class User(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=50)
# 连接数据库
async def init():
await Tortoise.init(
db_url="sqlite://./test.db",
modules={"models": ["__main__"]}
)
await Tortoise.generate_schemas()
# 异步查询
async def get_users():
users = await User.all()
for user in users:
print(user.name)
Tortoise-ORM 提供了类似 Django ORM 的查询接口,但其异步支持使得在高并发应用中表现更加出色。