greyli / bluelog

Check out the newer version (2024) of this project: https://github.com/greyli/greybook
MIT License
454 stars 662 forks source link

关于评论数目的可改进实现 #3

Closed jiangyanglinlan closed 1 year ago

jiangyanglinlan commented 6 years ago
  1. 主页每篇文章显示的评论数是这篇文章下的所有评论(包括未审核通过的), 主要代码如下:
{{ post.comments|length }}
  1. 文章详情页面显示的评论数是分页后当前页面的评论数, 而不是文章的总评论数, 主要的代码如下:
post = Post.query.get_or_404(post_id)
page = request.args.get('page', 1, type=int)
per_page = current_app.config['BLUELOG_COMMENT_PER_PAGE']
pagination = Comment.query.with_parent(post).filter_by(reviewed=True).order_by(Comment.timestamp.asc()).paginate(page, per_page)
comments = pagination.items
{{ comments|length }} Comments

解决方法:

我的实现是在 Post 类中新增了一个方法, 返回审核通过的评论列表:

class Post(db.Model):
    __tablename__ = 'posts'

    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(60))
    body = db.Column(db.Text)
    timestamp = db.Column(db.DateTime, default=datetime.now)
    category_id = db.Column(db.Integer, db.ForeignKey('categories.id'))
    comments = db.relationship('Comment', backref='post', cascade='all, delete-orphan')

    def reviewed_comments(self):
        return [comment for comment in self.comments if comment.reviewed is True]

这样的话, 在需要显示评论数量的地方就可以使用 {{ post.reviewed_comments()|length }}。

goodbad3 commented 5 years ago

作者好像没错把,filter_by(reviewed=True),都把未审核的过滤去了

greyli commented 5 years ago

@goodbad3 错误的是主页文章列表中显示的评论数量,这里没有过滤。

goodbad3 commented 5 years ago

那不就成了pagination.toal了。难道不是要每一页的评论数? @greyli , @jiangyanglinlan

greyli commented 5 years ago

文章页面的评论数字一般来说是应该显示总数的,这里的确可以用 pagination.total

greyli commented 5 years ago

备注一下。第 2 个问题已修复(54b9c0d)并将在第 2 次重印更新。

第 1 个问题因为涉及较大源码变动,暂时不修复,如果有第 2 版,再考虑更新书里的内容并修复。另外那个获取已审核评论的方法可以直接返回数量,作为属性使用,比如:

class Post(db.Model):
    # ...

    @property
    def reviewed_comments_count(self):
        return len([comment for comment in self.comments if comment.reviewed])

这样在模板里可以直接使用 {{ post.reviewed_comments_count }}

BrightHsu commented 4 years ago

看书至此也发现了同样的问题,我的解决办法是在工厂函数里注册了一个过滤器,过滤掉未通过审核的评论数,主页里渲染出的评论数量就能与文章页显示的评论数一致了,代码如下:

# 自定义过滤器函数
def register_template_filter(app):
    @app.template_filter()
    def reviewed(obj):
        num = 0
        for comment in obj:
            if comment.reviewed:
                num += 1
        return num

def create_app(*args, **kwargs):
    #...

    # 工厂函数里注册模板过滤器
    register_template_filter(app)  
    return app

然后再到模板里直接渲染:{{ post.comments|reviewed }}

greyli commented 1 year ago

感谢反馈,已在 https://github.com/greyli/new-bluelog/pull/14 处理。