Flask如何计算标签数量

时间:2013-05-17 09:29:25

标签: python sqlite sqlalchemy flask

我开发了带标记支持的简单博客。实际上我想添加标签云功能,我需要计算博客中使用的每个标签。 我的Blog和Tag模型如下所示:

class Blog(db.Model, ObservableModel):
    __tablename__ = "blogs"

    id = db.Column(db.Integer, db.Sequence('blog_id_seq'), primary_key=True)
    title = db.Column(db.String(200), unique=True, nullable=True)

    tags = relationship('Tag', secondary=tags_to_blogs_association_table)

class Post(db.Model, ObservableModel):
    __tablename__ = "posts"

    ......................

    blog = relationship('Blog', backref = db.backref('blogs', lazy='dynamic'))
    tags = relationship('Tag', secondary=tags_to_posts_association_table)

class Tag(db.Model):
    __tablename__ = "tags"

    id = db.Column(db.Integer, db.Sequence('post_id_seq'), primary_key=True)
    title = db.Column(db.String(30), unique=False, nullable=True)

我想收集像tag_name : count这样的对词典,只有一种方法是通过检索包含标签项目的帖子来迭代Blog.tags集合。 实际上我不确定它是最好的(从性能的角度来看)解决方案,也许flask-sqlalchemy提供了连接功能? 问题:如何使用Flask-SQLAlchemy查询在Python中实现如下:

select
    t.id,
    t.title,
    count(post_id)
from tags t
join tags_to_blogs b on t.id=b.tag_id
join tags_to_posts p on t.id=p.tag_id
group by (t.id)
having b.blog_id=1

2 个答案:

答案 0 :(得分:2)

试试这个:

query = db.session.query(Tag, db.count(Post.id))
query = query.filter(
    (tags_to_posts_association_table.tag_id == Tag.id) & \
    (tags_to_posts_association_table.post_id == Post.id)
)
query = query.group_by(Tag.id)

这会生成此查询:

SELECT tags.id AS tags_id, tags.title AS tags_title, count(posts.id) AS count_1 
FROM tags, posts, tags_to_posts 
WHERE tags_to_posts.tag_id = tags.id AND tags_to_posts.post_id = posts.id GROUP BY tags.id

更清洁的方式可能是这样的:

query = db.session.query(Tag, db.func.count(Post.id))
# This works but the preferred way is what's below it
#query = query.join(tags_to_posts_association_table, Post)
query = query.join(Post.tags)
query = query.group_by(Tag.id)

这会生成此查询:

SELECT tags.id AS tags_id, tags.title AS tags_title, count(posts.id) AS count_1 
FROM tags INNER JOIN tags_to_posts ON tags.id = tags_to_posts.tag_id INNER JOIN posts ON posts.id = tags_to_posts.post_id GROUP BY tags.id

所有这些产生相同的结果,你可以像这样链接它们:

query = db.session.query(Tag.title, db.func.count(Post.id)).join(Post.tags).group_by(Tag.id)

# This will give you a dictionary with keys the tag titles, and values the count of each
# Because you can iterate over the query, which will give you the results
# Or you can use query.all() and use it as you prefer.
results = dict(query)

另外,我不确定它是db.func.count还是db.count。无论如何,您始终可以from sqlalchemy import func并使用func.count

答案 1 :(得分:1)

我会这样做(伪代码,不记得正确的炼金术语法,但你应该能够'转换'它很容易安静)

tags = Tags.findAll()
for tag in tags:
    myDict[tag] = Post.find(tags=tag).count()

并且你应该在myDict中拥有所有的标签