【问题标题】:Flask SQLAlchemy - How to order query result by count of ForeignKey variableFlask SQLAlchemy - 如何按 ForeignKey 变量的计数排序查询结果
【发布时间】:2019-07-02 15:43:05
【问题描述】:

我正在使用 Flask-SQLAlchemy 实现博客文章类型的 Flask 应用程序。

我正在尝试根据收到的每篇博文的总点赞数来排序博文。我尝试使用带有查询session.query(Post).order_by(Post.likes_count.desc()).all() 的 SQLALchemy 混合属性,这类似于之前提出的问题的解决方案here

它抛出错误AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Post.likes has an attribute 'count'

有没有办法使用需要提供给分页功能的喜欢计数来获取帖子顺序。

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20))
    email = db.Column(db.String(120))
    likes = db.relationship('Like', backref='user',lazy='dynamic',foreign_keys='Like.user_id')
    def __repr__(self):
        return f"User('{self.username}', '{self.email}')"

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100))
    date_posted = db.Column(db.DateTime, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    likes = db.relationship('Like', backref='post', lazy='dynamic')

    @hybrid_property
    def likes_count(self):
        return self.likes.count()

    def __repr__(self):
        return f"Post('{self.title}', '{self.date_posted}')"

class Like(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))

这个问题类似于How to order by count of many-to-many relationship in SQLAlchemy? 但是我无法使用答案/cmets 中提到的lencount() 方法获得查询结果。

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    我这样做的方法是使用 sqlalchemy 的 func functionality,它只是反映了一个 SQL 函数。在这种情况下,很可能是以下情况:

    from sqlalchemy import func
    
    session.query(Post).join(Like).group_by(Post.id).order_by(func.count().desc()).all()
    

    此查询会产生类似于以下原始 SQL 的结果(尽管我只是试图通过不写出所有内容来使其更简洁):

    SELECT post.*
    FROM post
    JOIN like ON like.post_id = post.id
    GROUP BY post.id
    ORDER BY count() desc
    

    希望这会有所帮助!

    【讨论】:

    • 这行得通。但是结果不包含有 0 个喜欢的行。所以,我不得不使用外连接而不是连接来获得 0 个喜欢的结果行。 session.query(Post).outerjoin(Like).group_by(Post.id).order_by(func.count().desc()).all()
    • 很好的解决方案!乐于助人
    • 我必须阅读 w3school sql 教程才能理解您的上述表达式。我想知道,是否可以根据喜欢的函数结果组合和它创建的时间对结果进行排序。这类似于帖子排名的 reddit 热度。即,如果我添加 ``` def hotness(self): return (self.likes.count() / (datetime.now() -self.date_created).days) ```
    • 是的,您可以按表达式链接顺序,它将使用第二列打破第一列中的关系。类似于 SQL 中的 ORDER BY count() desc, date_posted 或 SQLAlchemy 中的 .order_by(func.count().desc(), Post.date_posted)。这是你要找的吗?
    • 我会将热度定义为混合属性,我会将其附加到我的答案中以使其更具可读性
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 2019-04-23
    • 2015-02-15
    • 2021-12-24
    • 2013-12-15
    相关资源
    最近更新 更多