You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Peewee实现多关联表数据按时间戳统一排序查询?

Peewee实现多关联表活动的统一时间排序展示

需求说明

需要从User关联的Tweet和Facebook表中取出某用户的所有活动(推文、帖子),并按时间戳降序(最新优先)混合展示,且无法将数据合并到单个Activity表。

现有问题

当前代码只能分别对推文和帖子排序展示,无法将两类记录混合后统一按时间排序。

解决方案

利用Peewee的Union操作,将两个表的查询结果合并为一个结构统一的数据集,再按时间戳排序。核心是让两个查询返回相同字段(可额外添加标识字段区分活动来源),再执行联合查询并排序。

修改后的完整代码

import datetime
from peewee import *

db = SqliteDatabase(':memory:')

class BaseModel(Model):
    class Meta:
        database = db

class User(BaseModel):
    username = TextField()

    @property
    def tweets_date_desc(self):
        return self.tweets.order_by(Tweet.timestamp.desc())

    @property
    def posts_date_desc(self):
        return self.posts.order_by(Facebook.timestamp.desc())

    @property
    def all_activities_date_desc(self):
        # 构造推文查询:指定返回字段,添加来源标识
        tweet_query = (Tweet
                       .select(Tweet.timestamp, Tweet.content, 
                               Value('tweet').alias('source'))
                       .where(Tweet.user == self))
        # 构造脸书帖子查询:保持与推文查询相同的返回字段结构
        fb_query = (Facebook
                    .select(Facebook.timestamp, Facebook.content, 
                            Value('facebook').alias('source'))
                    .where(Facebook.user == self))
        # 合并两个查询,按时间戳降序排序
        union_query = tweet_query.union(fb_query).order_by(SQL('timestamp').desc())
        return union_query

class Tweet(BaseModel):
    content = TextField()
    timestamp = DateTimeField(default=datetime.datetime.now)
    user = ForeignKeyField(User, backref='tweets')

class Facebook(BaseModel):
    content = TextField()
    timestamp = DateTimeField(default=datetime.datetime.now)
    user = ForeignKeyField(User, backref='posts')

测试与使用示例

# 初始化数据库并插入测试数据
db.connect()
db.create_tables([User, Tweet, Facebook])

# 创建测试用户
user = User.create(username='huey')

# 插入不同时间的活动记录
Tweet.create(user=user, content='第一条推文', timestamp=datetime.datetime(2024, 5, 1, 10, 0))
Facebook.create(user=user, content='第一条脸书帖子', timestamp=datetime.datetime(2024, 5, 1, 11, 0))
Tweet.create(user=user, content='第二条推文', timestamp=datetime.datetime(2024, 5, 1, 12, 0))
Facebook.create(user=user, content='第二条脸书帖子', timestamp=datetime.datetime(2024, 5, 1, 9, 0))

# 获取并展示混合排序的活动
print(f"用户 {user.username} 的所有活动(按时间降序):")
for activity in user.all_activities_date_desc:
    print(f"[{activity.source}] {activity.timestamp} - {activity.content}")

关键要点

  • 两个子查询必须返回相同数量和类型的字段,这里统一选择timestamp、content,并添加source字段区分活动类型(可选,但便于识别来源)
  • 使用union()合并查询结果,默认会自动去重;如果需要保留重复记录,可改用union_all()
  • 合并后的数据集直接通过order_by()按时间戳降序排序,实现统一展示

内容的提问来源于stack exchange,提问作者Bill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:22:03