帖子详情
动态加载帖子详情数据
在 blueprints/post.py 中,添加 post_detail 视图函数,代码如下。
@bp.get("/post/detail/<int:post_id>")
def post_detail(post_id):
post = PostModel.query.get(post_id)
post.read_count += 1
db.session.commit()
return render_template("front/post_detail.html", post=post)
上述代码中,在 URL 中定义了一个 post_id 参数,然后提取帖子对象,并且把帖子对象传到了 post_detail.html 模板中。为了能访问帖子详情,首先要在首页的帖子列表中补齐帖子标题的超链接,代码如下。
<p class="post-title">
<a href="{{ url_for('front.post_detail', post_id=post.id) }}">
{{ post.title }}
</a>
</p>
在帖子详情页中,把帖子相关的数据填充进去,如发表时间、作者等,代码如下。
...
<div class="post-container">
<h2>{{ post.title }}</h2>
<p class="post-info-group">
<span>发表时间:{{ post.create_time }}</span>
<span>作者:{{ post.author.username }}</span>
<span>所属板块:{{ post.board.name }}</span>
<span>阅读数:{{ post.read_count }}</span>
<span>评论数:{{ post.comments|length }}</span>
</p>
<article class="post-content" id="post-content">
{{ post.content|safe }}
</article>
</div>
...
现在重新加载帖子详情页面,可以看到帖子数据都能正常显示在页面中了。
发布评论
在帖子详情页面底部有一个 textarea 文本框,用于发布帖子评论。在 forms/post.py 中实现一个评论表单功能,代码如下。
class PublicCommentForm(BaseForm):
content = StringField(validators=[Length(
min=2, max=200, message="请输入正确长度的评论!")])
上述代码中,定义了 content 字段,发布评论只需要提交评论内容即可。然后在 blueprints/front.py 中,添加一个 public_comment 视图函数,并添加以下代码。
@bp.post("/post/<int:post_id>/comment")
@login_required
def public_comment(post_id):
form = PublicCommentForm(request.form)
if form.validate():
content = form.content.data
comment = CommentModel(content=content, post_id=post_id, author=g.user)
db.session.add(comment)
db.session.commit()
else:
for message in form.messages:
flash(message)
return redirect(url_for("front.post_detail", post_id=post_id))
上述代码中,我们把帖子 id 通过 URL 参数传过来,然后通过表单获取评论内容。发布评论的视图函数必须在登录的条件下才能访问,因此加了 login_required 装饰器。然后通过 g.user 即可获取到当前登录的用户作为该条评论的作者。评论发表成功,则重新加载帖子详情页面,这样用户就能看到最新的评论数据。评论发表失败,则把表单错误信息传到 flash 中,同时重新加载页面来显示错误信息。在 templates/front/post_detail.html 中添加显示错误信息和表单 URL,代码如下。

接着在 templates/front/post_detail.html 中,把帖子所有的评论循环显示出来,代码如下。

现在重新访问任何一篇帖子的详情页,在登录的情况下都可以正常发表评论了。但是,新发表的评论会显示在帖子列表的后面,为了实现通过 post.comments 获取的评论列表能根据发表时间倒序排序,在 CommentModel 中将 post 的 relationship 代码修改如下。
...
post = db.relationship("PostModel", backref=db.backref('comments', order_by=create_time.desc()))
...
这样,就可以自动按照评论发表时间倒序排序了。