Peewee
最后修改于 2024 年 1 月 29 日
Peewee 教程展示了如何使用 Python Peewee ORM。
对象关系映射 (ORM) 是一种从面向对象语言访问关系数据库的技术。 它是 Python 数据库 API 的抽象。
Python Peewee
Peewee 是一个简单且小巧的 Python ORM 工具。 它支持 SQLite、MySQL 和 PostgreSQL。
$ pipenv install peewee
我们安装 peewee
模块。
Peewee 映射
一个 Model
映射到数据库表,一个 Field
映射到表列,而 instance
映射到表行。
Peewee 使用 MySQLDatabase
用于 MySQL,PostgresqlDatabase
用于 PostgreSQL,以及 SqliteDatabase
用于 SQLite。 在本文中,我们使用 SQLite 数据库。
Peewee 字段类型
Peewee 模型中的字段类型定义了模型的存储类型。 它们被转换为相应的数据库列类型。
字段类型 | SQLite | PostgreSQL | MySQL |
---|---|---|---|
CharField | varchar | varchar | varchar |
TextField | text | text | longtext |
DateTimeField | datetime | timestamp | datetime |
IntegerField | integer | integer | integer |
BooleanField | smallint | 布尔值 | bool |
FloatField | real | real | real |
DoubleField | real | double precision | double precision |
BigIntegerField | integer | bigint | bigint |
DecimalField | decimal | numeric | numeric |
PrimaryKeyField | integer | serial | integer |
ForeignKeyField | integer | integer | integer |
DateField | date | date | date |
TimeField | time | time | time |
该表列出了 Peewee 字段类型以及相应的 SQLite、PostgreSQL 和 MySQL 列类型。
Peewee 模型定义
在第一个例子中,我们创建一个简单的数据库表。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' Note.create_table() note1 = Note.create(text='Went to the cinema') note1.save() note2 = Note.create(text='Exercised in the morning', created=datetime.date(2018, 10, 20)) note2.save() note3 = Note.create(text='Worked in the garden', created=datetime.date(2018, 10, 22)) note3.save() note4 = Note.create(text='Listened to music') note4.save()
该示例在 SQLite 中创建一个 notes
数据库表。
db = peewee.SqliteDatabase('test.db')
我们初始化一个 test.db
SQLite 数据库。 这将在文件系统中创建一个 test.db
文件。
class Note(peewee.Model): ...
我们定义一个名为 Note
的数据库模型。 Peewee 模型继承自 peewee.Model
。
text = peewee.CharField() created = peewee.DateField(default=datetime.date.today)
我们指定模型字段。 我们有一个 CharField
和一个 DateField
。 CharField
是一个用于存储字符串的字段类。 DateField
是一个用于存储日期的字段类。 如果未指定,它会采用默认值。
class Meta: database = db db_table = 'notes'
在 Meta
类中,我们定义对数据库和数据库表名称的引用。
Note.create_table()
该表是从带有 create_table
的模型创建的。
note1 = Note.create(text='Went to the cinema') note1.save()
我们创建并保存一个新的实例。
sqlite> select * from notes; 1|Went to the cinema|2018-11-01 2|Exercised in the morning|2018-10-20 3|Worked in the garden|2018-10-22 4|Listened to music|2018-11-01
我们验证数据。
Peewee 删除表
该表使用 drop_table
模型方法删除。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' Note.drop_table()
该示例删除了 notes
表。
Peewee insert_many
insert_many
方法允许批量创建。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' Note.create_table() data = [ { 'text': 'Tai chi in the morning', 'created': datetime.date(2018, 10, 20) }, { 'text': 'Visited friend', 'created': datetime.date(2018, 10, 12) }, { 'text': 'Went to cinema', 'created': datetime.date(2018, 10, 5) }, { 'text': 'Listened to music', 'created': datetime.date(2018, 10, 28) }, { 'text': 'Watched TV all day', 'created': datetime.date(2018, 10, 14) }, { 'text': 'Worked in the garden', 'created': datetime.date(2018, 10, 22) }, { 'text': 'Walked for a hour', 'created': datetime.date(2018, 10, 28) } ] with db.atomic(): query = Note.insert_many(data) query.execute()
该代码示例在一个批量创建操作中重新创建 notes
表。
data = [ { 'text': 'Tai chi in the morning', 'created': datetime.date(2018, 10, 20) }, { 'text': 'Visited friend', 'created': datetime.date(2018, 10, 12) }, { 'text': 'Went to cinema', 'created': datetime.date(2018, 10, 5) }, { 'text': 'Listened to music', 'created': datetime.date(2018, 10, 28) }, { 'text': 'Watched TV all day', 'created': datetime.date(2018, 10, 14) }, { 'text': 'Worked in the garden', 'created': datetime.date(2018, 10, 22) }, { 'text': 'Walked for a hour', 'created': datetime.date(2018, 10, 28) } ]
我们在字典列表中定义数据。
with db.atomic(): query = Note.insert_many(data) query.execute()
我们执行批量操作。 atomic
方法将批量操作放入事务中。
Peewee 选择所有实例
select
方法用于检索定义的模型的实例。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' notes = Note.select() for note in notes: print('{} on {}'.format(note.text, note.created))
该示例获取并显示所有 Note
实例。
notes = Note.select()
select
方法创建一个 SELECT 查询。 如果没有明确提供任何字段,则默认情况下查询将选择模型上定义的所有字段。
$ ./fetch_all.py Tai chi in the morning on 2018-10-20 Visited friend on 2018-10-12 Went to cinema on 2018-10-05 Listened to music on 2018-10-28 Watched TV all day on 2018-10-14 Worked in the garden on 2018-10-22 Walked for a hour on 2018-10-28
Peewee 使用 where 进行过滤
where
方法可以基于给定条件过滤数据。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' notes = Note.select().where(Note.id > 3) for note in notes: print('{} {} on {}'.format(note.id, note.text, note.created))
该示例检索所有 Id 大于 3 的行。
notes = Note.select().where(Note.id > 3)
where
方法对查询应用过滤条件。
$ ./where_clause.py 4 Listened to music on 2018-10-28 5 Watched TV all day on 2018-10-14 6 Worked in the garden on 2018-10-22 7 Walked for a hour on 2018-10-28
Peewee 多个 where 表达式
我们可以组合多个 where 表达式。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' notes = Note.select().where((Note.id > 2) & (Note.id < 6)) for note in notes: print('{} {} on {}'.format(note.id, note.text, note.created))
该示例检索所有 id 大于 2 且小于 6 的行。
notes = Note.select().where((Note.id > 2) & (Note.id < 6))
我们使用两个与 & 运算符组合的 where 表达式。
$ ./multiple_where_expr.py 3 Went to cinema on 2018-10-05 4 Listened to music on 2018-10-28 5 Watched TV all day on 2018-10-14
Peewee 检索单个实例
有两种方法可以选择单个实例; 它们都使用 get
方法。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' note1 = Note.select().where(Note.text == 'Went to cinema').get() print(note1.id) print(note1.text) print(note1.created) note2 = Note.get(Note.text == 'Listened to music') print(note2.id) print(note2.text) print(note2.created)
该示例展示了如何以两种方式检索单个实例。
note1 = Note.select().where(Note.text == 'Went to cinema').get()
我们可以使用 Note.select().where().get
方法链。
note2 = Note.get(Note.text == 'Listened to music')
还有一个 Note.get
快捷方法,它做同样的事情。
$ ./single_instance.py 3 Went to cinema 2018-10-05 4 Listened to music 2018-10-28
Peewee 选择特定列
在 select
方法中,我们可以指定要包含在查询中的列的名称。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' notes = Note.select(Note.text, Note.created).limit(2) output = [e for e in notes.tuples()] print(output)
该示例包括两列:text 和 created。 Id 被跳过。 我们将查询限制为两个实例。
$ ./columns.py [('Tai chi in the morning', datetime.date(2018, 10, 20)), ('Visited friend', datetime.date(2018, 10, 12))]
Peewee 计数实例
要计算表中模型实例的数量,我们可以使用 count
方法。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' n = Note.select().count() print(n) n2 = Note.select().where(Note.created >= datetime.date(2018, 10, 20)).count() print(n2)
该示例计算所有实例的数量以及日期等于或晚于 2018/10/20 的实例的数量。
$ ./count_instances.py 7 4
Peewee 显示 SQL 语句
生成的 SQL 语句可以使用 sql
方法显示。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' note3 = Note.select().where(Note.id == 3) print(note3.sql())
该示例显示了 ORM 查询转换为的 SQL。
$ ./show_sql.py ('SELECT "t1"."id", "t1"."text", "t1"."created" FROM "notes" AS "t1" WHERE ("t1"."id" = ?)', [3])
Peewee offset, limit
使用 offset
和 limit
属性,我们可以定义实例的初始跳过和要包含在 select
中的实例数。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' notes = Note.select().offset(2).limit(3) for note in notes: print(note.id, note.text, note.created)
该示例返回三个实例,从第二个实例开始。
$ ./offset_limit.py 3 Went to cinema 2018-10-05 4 Listened to music 2018-10-28 5 Watched TV all day 2018-10-14
Peewee 排序
检索到的实例可以使用 order_by
排序。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' print('Ascending order') print('*****************************') notes = Note.select(Note.text, Note.created).order_by(Note.created) for note in notes: print(note.text, note.created) print() print('Descending order') print('*****************************') notes = Note.select(Note.text, Note.created).order_by(Note.created.desc()) for note in notes: print(note.text, note.created)
该代码示例按创建日期对实例进行排序。
notes = Note.select(Note.text, Note.created).order_by(Note.created)
此行返回按创建日期升序排序的 note 实例。
notes = Note.select(Note.text, Note.created).order_by(Note.created.desc())
要按升序检索笔记,我们在字段上附加 desc
方法。
Ascending order ***************************** Went to cinema 2018-10-05 Visited friend 2018-10-12 Watched TV all day 2018-10-14 Tai chi in the morning 2018-10-20 Worked in the garden 2018-10-22 Listened to music 2018-10-28 Walked for a hour 2018-10-28 Descending order ***************************** Listened to music 2018-10-28 Walked for a hour 2018-10-28 Worked in the garden 2018-10-22 Tai chi in the morning 2018-10-20 Watched TV all day 2018-10-14 Visited friend 2018-10-12 Went to cinema 2018-10-05
这是 note 实例的有序列表。
Peewee 删除实例
delete_by_id
方法删除由其 Id 标识的实例。 它返回已删除的实例数。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' n2 = Note.delete_by_id(1) print(n2)
该示例删除 Id 为 1 的 Note
实例。
Peewee 删除多个实例
要删除更多实例,我们调用 delete
方法。 它返回成功删除的实例数。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' query = Note.delete().where(Note.id > 3) n = query.execute() print('{} instances deleted'.format(n))
在该示例中,我们删除所有 Id 大于 3 的实例。
$ ./delete_instances.py 4 instances deleted
在我们的例子中,我们删除了四个 Note
实例。
Peewee 更新实例
update
方法更新一个实例。 它返回成功更新的实例数。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Note(peewee.Model): text = peewee.CharField() created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'notes' query = Note.update(created=datetime.date(2018, 10, 27)).where(Note.id == 1) n = query.execute() print('# of rows updated: {}'.format(n))
该示例修改了 Id 为 1 的笔记的创建日期。
Peewee 一对多关系
在以下示例中,我们将模型映射到现有表。 模型之间的关系是使用 ForeignKeyField
创建的。
BEGIN TRANSACTION; DROP TABLE IF EXISTS reservations; DROP TABLE IF EXISTS customers; CREATE TABLE IF NOT EXISTS customers(id INTEGER PRIMARY KEY, name TEXT); INSERT INTO customers(Name) VALUES('Paul Novak'); INSERT INTO customers(Name) VALUES('Terry Neils'); INSERT INTO customers(Name) VALUES('Jack Fonda'); INSERT INTO customers(Name) VALUES('Tom Willis'); CREATE TABLE IF NOT EXISTS reservations(id INTEGER PRIMARY KEY, customer_id INTEGER, created DATE, FOREIGN KEY(customer_id) REFERENCES customers(id)); INSERT INTO reservations(customer_id, created) VALUES(1, '2018-22-11'); INSERT INTO reservations(customer_id, created) VALUES(2, '2018-28-11'); INSERT INTO reservations(customer_id, created) VALUES(2, '2018-29-11'); INSERT INTO reservations(customer_id, created) VALUES(1, '2018-29-11'); INSERT INTO reservations(customer_id, created) VALUES(3, '2018-02-12'); COMMIT;
此 SQL 创建两个表:customers
和 reservations
。 两个表之间存在一对多关系:一个客户可以有多个预订。
sqlite> .read customers_reservations.sql
我们将 SQL 文件读入数据库。
#!/usr/bin/python import peewee import datetime db = peewee.SqliteDatabase('test.db') class Customer(peewee.Model): name = peewee.TextField() class Meta: database = db db_table = 'customers' class Reservation(peewee.Model): customer = peewee.ForeignKeyField(Customer, backref='reservations') created = peewee.DateField(default=datetime.date.today) class Meta: database = db db_table = 'reservations' customer = Customer.select().where(Customer.name == 'Paul Novak').get() for reservation in customer.reservations: print(reservation.id) print(reservation.created)
在该示例中,我们定义了两个映射到表的模型。 然后我们选择一个客户并显示他的预订。
customer = peewee.ForeignKeyField(Customer, backref='reservations')
Customer
和 Reservation
模型之间的关系是使用 ForeignKeyField
创建的。 backref
属性设置了我们如何从客户引用预订。
for reservation in customer.reservations:
客户实例具有一个属性 reservations
,其中包含相应的预订。
$ ./one2many.py 1 2018-22-11 4 2018-29-11
来源
在本文中,我们介绍了 Python Peewee ORM。
作者
列出所有 Python 教程。