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的查询效果

5 回复

回复不能用 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 里面。已经解决问题啦,感谢耐心的大兄弟!

回到顶部