erDiagram
USER ||--o{ POST : posts
USER ||--o{ COMMENT : comments
POST ||--o{ COMMENT : comments
USER {
int id PK
varchar username "UK,IX"
varchar email UK
varchar password_hash
boolean is_active
datetime created_at
}
POST {
int id PK
varchar title
text content
int author_id FK
datetime published_at
boolean is_published
}
COMMENT {
int id PK
text text
int user_id FK
int post_id FK
datetime created_at
}
with db: # 查询所有用户 print("\n--- 所有用户 ---") for user in User.select(): print(f"ID: {user.id}, Username: {user.username}, Email: {user.email}, Active: {user.is_active}")
# 查询特定用户 (使用 .get_or_none() 方法,未找到返回 None) print("\n--- 特定用户 (not_exist_user) ---") not_exist_user = User.get_or_none(User.username == 'not_exist_user') if not_exist_user: print(f"找到了 Not Exist User: {not_exist_user.username}") else: print("未找到 Not Exist User。")
# 查询所有已发布的文章 print("\n--- 所有已发布的文章 ---") published_posts = Post.select().where(Post.is_published == True) for post in published_posts: print(f"Title: {post.title}, Author: {post.author.username}") # .author 是一个 User 对象
# 查询 Alice 发布的所有文章 print("\n--- Alice 发布的所有文章 ---") alice_posts = Post.select().join(User).where(User.username == 'alice') # 或者直接使用 alice 实例 # alice = User.get(User.username == 'alice') # alice_posts = Post.select().where(Post.author == alice) for post in alice_posts: print(f"Title: {post.title}, Content: {post.content[:30]}...")
# 查询包含特定关键词的文章,并按发布时间倒序 print("\n--- 包含'Peewee'关键词的文章,按发布时间倒序 ---") peewee_posts = Post.select().where(Post.title.contains('Peewee')).order_by(Post.published_at.desc()) for post in peewee_posts: print(f"Title: {post.title}, Published At: {post.published_at}")
# 限制和偏移 (Limit & Offset) print("\n--- 最新的2篇文章 ---") latest_posts = Post.select().order_by(Post.created_at.desc()).limit(2) for post in latest_posts: print(f"Title: {post.title}")
# 查询所有评论,并同时获取评论的用户和文章信息 (N+1 问题优化) print("\n--- 查询所有评论及关联的用户和文章 ---") # `prefetch` 会执行两次查询:一次获取Comment,一次获取关联的User和Post for comment in Comment.select().prefetch(User, Post): print(f"评论: '{comment.text}' by {comment.user.username} on '{comment.post.title}'")
# 指定 select 哪些列 print("\n--- 仅查询用户名和邮箱 ---") for user_data in User.select(User.username, User.email): print(f"Username: {user_data.username}, Email: {user_data.email}")
5.3.2 复杂的 where 条件
使用 & (AND) 和 | (OR) 操作符来组合条件。
1 2 3 4 5 6 7 8 9 10 11 12 13
with db: # 查询 Alice 或 Bob 发布且已发布的文章 print("\n--- Alice 或 Bob 发布且已发布的文章 ---") users = (User.username == 'alice') | (User.username == 'bob') published_by_alice_or_bob = Post.select().join(User).where(users & (Post.is_published == True)) for post in published_by_alice_or_bob: print(f"Title: {post.title}, Author: {post.author.username}")
# 使用 `in_` 和 `not_in` print("\n--- 用户名在列表中的用户 ---") users_in_list = User.select().where(User.username.in_(['alice', 'charlie'])) for user in users_in_list: print(f"Username: {user.username}")
5.3.3 原始 SQL
当 Peewee 的查询 API 无法满足需求时,可以使用原始 SQL。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
with db: print("\n--- 原始 SQL 查询 (所有用户) ---") cursor = db.execute_sql('SELECT id, username, email FROM users;') for row in cursor.fetchall(): print(f"ID: {row[0]}, Username: {row[1]}, Email: {row[2]}")
print("\n--- 原始 SQL 查询 (带参数) ---") # 参数化查询防止 SQL 注入 username_param = 'bob' cursor = db.execute_sql('SELECT * FROM users WHERE username = ?;', (username_param,)) bob_user_raw = cursor.fetchone() if bob_user_raw: print(f"Raw query found Bob: {bob_user_raw}")
# 通过 Model.raw() 返回 Model 实例 print("\n--- Model.raw() 查询 ---") raw_query_users = User.raw('SELECT * FROM users WHERE is_active = ?', True) for user in raw_query_users: print(f"Raw query model: {user.username}")
with db: # 模拟一个事务,其中一个操作会失败 try: with db.atomic(): # 开启一个事务 print("\n--- 事务开始 ---") # 这是一个成功的操作 User.create(username='transaction_user_1', email='t1@example.com', password_hash='t1') print("创建了 transaction_user_1")
# 这是一个会失败的操作 (attempt to create a user with existing unique username 'alice') User.create(username='alice', email='t2@example.com', password_hash='t2') print("尝试创建 transaction_user_2 (应该失败)")