Peewee ORM 查询构建器深度解析
概述
Peewee 是一个轻量级但功能强大的 Python ORM 框架,其核心查询构建器提供了灵活且直观的方式来构建和执行 SQL 查询。本文将深入探讨 Peewee 的查询构建器功能,帮助开发者更好地理解和使用这一强大工具。
表结构定义
在 Peewee 中,我们可以通过两种方式定义表结构:
# 显式声明列
Person = Table('person', ('id', 'first', 'last'))
# 不声明列,通过.c属性动态访问
Reminder = Table('reminder')
最佳实践:建议显式声明列,这样可以获得更好的代码提示和类型检查支持。
数据库绑定
在实际应用中,我们需要将表绑定到数据库连接:
db = SqliteDatabase('my_app.db')
Person = Person.bind(db)
绑定后,执行查询时就不需要每次都传递数据库连接对象了。
查询基础
简单查询
# 查询前3条笔记并按时间排序
query = Note.select().order_by(Note.timestamp).limit(3)
for note_dict in query:
print(note_dict['content'])
注意:默认返回字典格式的结果,也可以通过.tuples()
、.namedtuples()
或.objects()
方法指定不同的结果容器。
带条件的查询
# 查询2018年以后的笔记及其作者信息
query = (Note
.select(Note.content, Note.timestamp, Person.first, Person.last)
.join(Person, on=(Note.person_id == Person.id))
.where(Note.timestamp >= datetime.date(2018, 1, 1))
.order_by(Note.timestamp)
.namedtuples())
聚合查询
# 查询笔记数量最多的用户
name = Person.first.concat(' ').concat(Person.last)
query = (Person
.select(name.alias('name'), fn.COUNT(Note.id).alias('count'))
.join(Note, JOIN.LEFT_OUTER, on=(Note.person_id == Person.id))
.group_by(name)
.order_by(fn.COUNT(Note.id).desc()))
关键点:
- 使用
fn
对象调用SQL函数 .alias()
方法用于指定列别名- 可以将表达式存储在变量中复用
高级查询技巧
表别名与子查询
# 查询每个人最新发布的笔记
NA = Note.alias('na')
max_note = (NA
.select(NA.person_id, fn.MAX(NA.timestamp).alias('max_ts'))
.group_by(NA.person_id)
.alias('max_note'))
query = (Note
.select(Note.content, Note.timestamp, Person.first, Person.last)
.join(max_note, on=((max_note.c.person_id == Note.person_id) &
(max_note.c.max_ts == Note.timestamp)))
.join(Person, on=(Note.person_id == Person.id)))
动态列访问
对于未显式声明列的表,可以使用.c
属性访问列:
query = (Reminder
.select(Reminder.c.alarm, Note.content)
.join(Note, on=(Reminder.c.note_id == Note.id))
数据操作
插入数据
# 单条插入
zaizee_id = Person.insert(first='zaizee', last='cat').execute()
# 批量插入
people = [
{'first': 'Bob', 'last': 'Foo'},
{'first': 'Herb', 'last': 'Bar'}]
Person.insert(people).execute()
更新数据
# 简单更新
Person.update(last='Baze').where(Person.first == 'Bob').execute()
# 原子更新
PageView.update({PageView.count: PageView.count + 1})
.where(PageView.url == some_url)
.execute()
删除数据
# 直接删除
Note.delete().where(Note.timestamp < datetime.date(2018, 1, 1)).execute()
# 使用子查询删除
foo_people = Person.select(Person.id).where(Person.last == 'Foo')
Note.delete().where(Note.person_id.in_(foo_people)).execute()
复杂查询示例
递归CTE查询
# 计算斐波那契数列前10项
base = Select(columns=(
Value(1).alias('n'),
Value(0).alias('fib_n'),
Value(1).alias('next_fib_n'))).cte('fibonacci', recursive=True)
n = (base.c.n + 1).alias('n')
recursive_term = Select(columns=(
n,
base.c.next_fib_n,
base.c.fib_n + base.c.next_fib_n)).from_(base).where(n < 10)
fibonacci = base.union_all(recursive_term)
query = fibonacci.select_from(fibonacci.c.n, fibonacci.c.fib_n)
总结
Peewee 的查询构建器提供了强大而灵活的方式来构建各种复杂SQL查询。通过本文的介绍,你应该已经掌握了:
- 基本的表定义和查询构建
- 高级查询技巧如子查询、表别名和递归CTE
- 数据操作的基本方法
- 复杂查询的构建思路
Peewee 的查询构建器设计既保持了SQL的灵活性,又提供了Pythonic的优雅语法,是构建数据库应用的强大工具。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考