第76课:轻量级 ORM:Peewee 入门
1. 学习目标
通过本课学习,你将能够:
- 理解 ORM 的概念及其在 Python 中的作用。
- 掌握 Peewee 的安装、配置及基本使用方法。
- 使用 Peewee 定义数据模型,并完成对数据库的增删改查(CRUD)操作。
- 了解 Peewee 与不同数据库后端(如 SQLite、MySQL、PostgreSQL)的连接配置。
2. 核心概念
什么是 ORM?
ORM(Object-Relational Mapping,对象关系映射)是一种技术,它允许我们使用面向对象的 Python 代码来操作数据库,而不需要直接编写 SQL 语句。你可以把 ORM 想象成一个"翻译官":你告诉它"给我所有名为'张三'的用户",它就去数据库里执行 SELECT * FROM user WHERE name='张三' 并把结果返回给你。
为什么选择 Peewee?
在 Python 中,Django ORM、SQLAlchemy 是功能强大且广为人知的 ORM 库。而 Peewee 是一个追求 轻量、简洁、易用 的 ORM。它非常适合:
- 中小型项目。
- 快速原型开发。
- 学习 ORM 的核心概念。
- 不需要庞大框架,但希望用优雅的方式操作数据库的场景。
核心概念图解
- 模型类 (Model):对应数据库中的一张表。用 Python 类定义。
- 字段 (Field):模型类中的属性,对应表中的列(如
CharField,IntegerField)。 - 实例 (Instance):模型类的一个对象,对应表中的一行数据。
- 查询 (Query):通过模型类的方法生成,用于获取、修改或删除数据。
3. 代码示例
以下示例使用内置的 SQLite 数据库,无需额外安装数据库服务器。
# 1. 安装 Peewee
# 在终端运行: pip install peewee
# 2. 导入必要的模块
from peewee import *
# 3. 定义数据库连接(这里使用 SQLite)
# 数据库文件名为 `my_app.db`,如果不存在会自动创建
db = SqliteDatabase('my_app.db')
# 4. 定义基础模型类(可选,但推荐)
# 它可以让其他模型继承这个数据库连接配置,避免重复代码
class BaseModel(Model):
class Meta:
database = db
# 5. 定义具体的数据模型
class User(BaseModel):
# 定义字段:自增主键、用户名(唯一)、邮箱、注册时间
id = AutoField(primary_key=True)
username = CharField(unique=True, max_length=50)
email = CharField(null=True) # 允许为空
join_date = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])
class Meta:
table_name = 'users' # 指定表名,不写则默认为 'user'(小写类名)
class Tweet(BaseModel):
# 定义一个简单的"推文"模型
user = ForeignKeyField(User, backref='tweets') # 外键关联到 User, `backref` 允许通过 user.tweets 访问
content = TextField()
timestamp = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])
# 6. 连接数据库并创建表
db.connect()
# 创建表(如果不存在),`safe=True` 表示如果表已存在则跳过,不会报错
db.create_tables([User, Tweet])
# === 以下是 CRUD 操作示例 ===
# --- 创建(Create)---
# 创建一个用户实例并保存
new_user = User.create(username='alice', email='[email protected]')
print(f"创建用户: ID={new_user.id}, 用户名={new_user.username}")
# 创建一条推文,关联到 alice
alice = User.get(User.username == 'alice') # 先获取 alice 的实例
Tweet.create(user=alice, content='Hello, this is my first tweet!')
# --- 查询(Read)---
# 获取所有用户
all_users = User.select()
for user in all_users:
print(f"用户: {user.username}, 邮箱: {user.email}")
# 条件查询:获取用户名为'alice'的用户
alice = User.get(User.username == 'alice')
print(f"找到了 Alice: {alice.email}")
# 获取 alice 的所有推文 (使用 backref)
print("Alice 的推文:")
for tweet in alice.tweets: # `tweets` 就是之前在 ForeignKeyField 中定义的 backref
print(f" - {tweet.content} (时间: {tweet.timestamp})")
# --- 更新(Update)---
# 更新 alice 的邮箱
alice.email = '[email protected]'
alice.save() # 必须调用 .save() 方法才能保存更改
print(f"更新后的 Alice 邮箱: {User.get(User.username == 'alice').email}")
# --- 删除(Delete)---
# 删除一条推文
first_tweet = Tweet.get() # 获取第一条推文
print(f"删除推文: {first_tweet.content}")
first_tweet.delete_instance()
# 关闭数据库连接(良好的实践)
db.close()
运行后,数据库中将有 users 和 tweet 两张表,并完成了增删改查的演示。
4. 实践练习
练习一:修改与更新
- 创建一个新用户
bob,邮箱为[email protected]。 - 为
bob发布两条内容不同的推文。 - 查询
bob的所有推文并打印其内容。
练习二:条件删除
- 编写代码,删除
User表中所有邮箱为空的用户。 - 删除后,查询并打印剩余用户列表,验证操作是否成功。
练习三:模型设计
- 设计一个
Product(商品) 模型,包含字段:商品名称、价格(小数)、库存数量、上架状态(布尔值)。 - 使用 Peewee 创建这个表。
- 插入一条测试数据(例如:商品名 "Python书",价格 49.99,库存 100,状态为 True)。
5. 常见错误
-
忘记
save():修改了模型实例的属性后,必须调用.save(),否则更改不会持久化到数据库。user.username = 'new_name' # user.save() # 忘了这行,数据库不会改变! -
字段名与 Python 关键字冲突:如果字段名是 Python 关键字(如
type,class),需要使用db_column参数重命名。class Article(BaseModel): type_ = CharField(max_length=20, db_column='type') # 数据库列名为 'type' -
查询未调用
.execute()或迭代:User.select()返回的是一个查询对象,只有在迭代(如for user in query)或调用.execute()时才会真正执行查询。 -
外键关联错误:定义
ForeignKeyField时,model参数应指向另一个模型类,而不是字符串。如果需要自关联,需要特殊处理。 -
数据库未创建就操作:确保在插入数据前,已经调用了
db.connect()和db.create_tables()。
6. 小结
本课我们学习了:
- ORM 的价值:它让我们用操作 Python 对象的方式来与数据库交互,提升开发效率和代码可维护性。
- Peewee 的核心三要素:
- 数据库连接 (
SqliteDatabase,PostgresqlDatabase等)。 - 模型定义 (继承
Model的类,包含Field)。 - 数据库表创建 (
create_tables)。
- 数据库连接 (
- 基本 CRUD 操作:
- 增:
Model.create()或instance.save()。 - 查:
Model.select(),Model.get()。 - 改:修改实例属性后调用
instance.save()。 - 删:
instance.delete_instance()。
- 增:
- 外键关联:使用
ForeignKeyField建立模型间关系,并通过backref反向访问。
掌握了 Peewee 的基础,你就拥有了用 Python 代码优雅管理数据的强大工具。在下一课,我们将转向一个全新的领域——使用 Tkinter 构建图形用户界面(GUI)程序。