Python中如何用peewee实现类似Django ORM的查询效果
本人新入坑的小白,如有不对的地方请包涵~~~!
在 django 中代码如下:
模型定义:
class Friends(models.Model):
first_id = models.IntegerField()
second_id = models.IntegerField()
class Meta:
unique_together=('first_id', 'second_id',)
查询语句如下:
friend_list_info = []
friend_list1 = Friends.objects.filter(first_id=Id).values_list('second_id', flat=True)
friend_list2 = Friends.objects.filter(second_id=Id).values_list('first_id', flat=True)
friend_list = list(friend_list1) + list(friend_list2)
意思是建立一个好友列表, 2 个人之间的关系是唯一的。通过输入的 Id ,查询出对应的好友的 Id 列表。 现在学习 sanic 框架用的 peewee,不知道应该如何实现。希望大家指教~!
Python中如何用peewee实现类似Django ORM的查询效果
回复不能用 Markdown ,代码比较难看:
friend_list = Friends.select(Friends.second_id).where(Friends.first_id=Id)
参考: https://peewee.readthedocs.io/en/latest/peewee/querying.html
Peewee本身就能实现大部分Django ORM的查询效果,只是语法略有不同。下面我通过几个常见场景对比说明:
1. 基础查询对比
# Django: User.objects.filter(age__gte=18, is_active=True)
# Peewee等效写法:
from peewee import *
class User(Model):
username = CharField()
age = IntegerField()
is_active = BooleanField()
class Meta:
database = db
# 查询
query = User.select().where((User.age >= 18) & (User.is_active == True))
# 或者用更简洁的写法
query = User.select().where(User.age >= 18, User.is_active == True)
2. 关联查询
# Django: Book.objects.filter(author__name='鲁迅')
# Peewee写法:
class Author(Model):
name = CharField()
class Book(Model):
title = CharField()
author = ForeignKeyField(Author, backref='books')
# 关联查询
query = Book.select().join(Author).where(Author.name == '鲁迅')
3. 聚合查询
# Django: User.objects.filter(city='北京').aggregate(Avg('age'))
# Peewee写法:
from peewee import fn
avg_age = User.select(fn.AVG(User.age)).where(User.city == '北京').scalar()
4. Q对象复杂查询
# Django: Q(age__gt=30) | Q(name__startswith='张')
# Peewee写法:
from peewee import OP
query = User.select().where(
(User.age > 30) | (User.name.startswith('张'))
)
5. 链式查询
# Peewee支持链式调用,类似Django的queryset
query = (User.select()
.where(User.is_active == True)
.order_by(User.created_at.desc())
.limit(10))
6. 预加载关联数据(类似select_related/prefetch_related)
# 预加载单条关联(类似select_related)
query = Book.select(Book, Author).join(Author)
# 预加载多条关联(类似prefetch_related)
from playhouse.shortcuts import prefetch
authors = Author.select()
books = Book.select()
query = prefetch(authors, books)
7. 原生SQL支持
# 如果确实需要Django的raw查询功能
query = User.raw('SELECT * FROM users WHERE age > %s', 18)
关键差异总结:
- Peewee用
&和|代替Django的Q对象 - 字段比较直接用Python运算符(
User.age >= 18) - 关联查询需要显式join
- 聚合函数在
fn模块中
实用技巧:
# 可以封装常用查询条件
def active_users():
return User.select().where(User.is_active == True)
# 动态构建查询
def build_query(min_age=None, city=None):
query = User.select()
if min_age:
query = query.where(User.age >= min_age)
if city:
query = query.where(User.city == city)
return query
Peewee的API设计更Pythonic,虽然语法不同但功能完全覆盖Django ORM的常见需求。熟悉后你会发现它比Django ORM更简洁直观。
总结:Peewee的查询语法更Pythonic,功能完全够用。
感谢回复,但是我想先构建这样的表, peewee 里好像没有 unique_together 只能设置单独的 unique. 然后是,查询结果应该是一个 id 的列表,上面得到是一个 object 。不知道能不能实现
1. peewee 没有 unique_together ,可以考虑直接用 primary_key = (‘first_id’, ‘second_id’),需要放在 class Meta 里(具体查下文档)
2. 得到 object 是正常的, ORM 框架就是这种思路。取法: for f in friend_list: f.first_id
感谢!!!关于 unique_together 我 google 到了用法相似的 indexes 写在 meta 里面。已经解决问题啦,感谢耐心的大兄弟!

