Reputation: 807
I'm implementing blog posts type Flask app using Flask-SQLAlchemy.
I'm trying to order the blog posts based on total number of likes each blog post received. I've tried using SQLALchemy hybrid property with query session.query(Post).order_by(Post.likes_count.desc()).all()
which is similar to solution to a question asked earlier here
It throws error AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Post.likes has an attribute 'count'
Is there a way to get posts order using likes count which needs to be fed to paginate function.
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'))
This question is similar to How to order by count of many-to-many relationship in SQLAlchemy? However I was not able to get query results with len
or count()
method mentioned in answer/comments.
Upvotes: 4
Views: 1971
Reputation: 13129
The way I would do it is by using sqlalchemy's func
functionality, which just mirrors a SQL function. In this case, that would most likely be the following:
from sqlalchemy import func
session.query(Post).join(Like).group_by(Post.id).order_by(func.count().desc()).all()
This query results in something like the following raw SQL (although I just tried to make it a little cleaner by not writing everything out):
SELECT post.*
FROM post
JOIN like ON like.post_id = post.id
GROUP BY post.id
ORDER BY count() desc
Hope this helps!
Upvotes: 5