Flask学习笔记 用户评论(comment) 第一部分

来源:互联网 发布:淘宝小二电话 编辑:程序博客网 时间:2024/06/09 18:51

评论功能是社交网站中非常重要的功能。通过以往上网的经验,我们可以大概分析一下需要实现的功能:1.在文章的详情页下创建一个用户评论区域。2.在详情页创建一个文本编辑器。3.对用户评论进行分页。4.显示文章的评论数。

分析完了需求之后,我们需要去确定一下基本思路。

首先用户进行评论时,存在两个一对多关系(注意这里不是多对多):1.一篇博客文章对应多个评论。 2.一个用户对应多个评论。

这里写图片描述

所以,需要建立一个comment类来分别实现上述的两个一对多关系。

新的comment类首先需要author_id与post_id两个外键分别于User和Post类建立联系,然后需要有代表评论内容的body,评论时间的timestamp以及用来保存html的body_html。

对应代码如下:

class Comment(db.Model):    __tablename__ = 'comments'    id = db.Column(db.Integer,primary_key=True)    body = db.Column(db.Text)    body_html = db.Column(db.Text)    timestamp = db.Column(db.Integer)    author_id = db.Column(db.Integer,db.ForeignKey('users.id'))    post_id = db.Column(db.Integer,db.ForeignKey('posts.id'))    #disabled代表是否显示评论。    disabled = db.Column(db.Boolean) 

然后再在User和Post类中建立相应的属性代表comments。

由于学习笔记是学到一半的时候开始写的,所以这里要解释一下如何对markdown中的html进行渲染。

使用过markdown编辑器的同学都知道,markdown这个东西可以通过输入一些特定的指令来实现html的一些功能,也就是说markdown命令≈实现相应功能所对应的html语言。

那么问题来了,现在有两种选择:1.直接提交(post)markdown生成的html源码给服务器,然后进行储存并渲染给用户观看。2.将markdown的源文本提交给服务器,在服务器端通过一个markdown处理器将其转换为html代码,再进行渲染。

这里肯定有人问:1.既然我通过2方法发送markdown原文本给服务器,那我的页面上还要markdown编辑器干嘛,直接输入相应的文本不就行了么。(我问的) 2.两个方法有何不同呢?一个提交的是html语言,一个提交的是markdown命令,感觉没啥区别呀。

现在可以回答第一个问题:这个问题很白痴,用户编辑的时候肯定要预览一下呀,就像程序员调试代码一样。

第二个问题:狗书上说:若采用方法1,如果有人进行攻击,将生成的html代码修改,就会造成markdown源文本与相应的html代码不匹配的后果。

但是我想了想,既然提交的html能被篡改,那提交的markdown文本不也能被篡改么,真被攻击了谁也不比谁安全呀。。所以这个问题先放一放。

我们后面先默认采用方法2。

对应的我们就需要在Comment类中创建一个方法,来实现markdown原文本 → html代码的一个转换。

以下是源码:

    @staticmethod    def on_changed_body(target,value):        allowed_tags = ['a','abbr','acronym','b','code','em','i','strong']        #allowed_tags代表允许使用的html标签。        target.body_html = bleach.linkify(bleach.clean(markdown(value,output_format='html'),tags=allowed_tags,strip=True)#markdown(value,output_format='html')value是指markdown源文本,output_format指转化为html代码。bleach.clean是一个内容清扫工具,将源文本中的一些错误语法清除。linkify则负责将相应的url转化为链接。                                                     

然后是对方法的调用:

db.event.listen(Post.body,'set',Post.on_changed_body)

‘set’代表只要这个类的实例的body属性有了新值,就调用on_changed_body函数。

然后对表单进行编写,这跟之前的文章表单基本一样比较简单,一个submitfield,一个pagedownfield。就不再多说了。

然后要进行视图函数的修改,因为评论这个东西是在文章的详情页下面的。所以要对之前的post视图函数进行修改,添加一个评论表单。

@main.route('/post/<int:id>',methods=['POST','GET'])def post(id):    post = Post.query.get_or_404(id)    form = CommentForm()    if form.validate_on_submit():        #post是Post类在Comment类中建立的回引(backref)同理author        comment = Comment(body=form.body.data,post=post,author=current_user._get_current_object())        db.session.add(comment)        flash('已评论')        return redirect(url_for('.post',id=post.id,page=-1))    page = request.args.get('page',1,type=int)    if page==-1:        page = (post.comments.count() - 1)/10 + 1    pagination = post.comments.order_by(Comment.timestamp.asc()).paginate(page,per_page=10,error_out=False)    comments = pagination.items    return render_template('post.html',posts=[post],form=form,comments=comments,pagination=pagination)

这里的思路是这样的: 用户点击submit按钮提交→数据库根据提交的内容进行更新 → 跳转到-1页(请求最后一页) → 当加载-1页的时候重新计算页数(因为加载-1页代表有新评论) → 分页、渲染。

有一个细节要提出来,阅读某人的文章是不需要权限的,但是评论时需要用户权限的,所以我们无法通过@login_required修饰器来把某些用户筛走。那该咋办呢?那只能在模板中实现这些功能了。通过jinja2模板提供的if结构可以轻易完成这个功能。

{% if current_user.can(Permission.COMMENT) %}<div class="comment-form">    {{ wtf.quick_form(form) }}</div>{% endif %}

同时要在首页中的文章列表区域添加一个按钮,来显示文章的评论数,按下之后进入文章评论页。

{% if current_user.is_authenticated %}    <a href="{{ url_for('.post',id=post.id) }}">        <span class="label label-primary">        {{ post.comments.count() }}Comments        </span>    </a>{% endif %}

显示评论的模板如下:

{% for comment in comments %}    <li class="comment">        <div class="comment-thumbnail">            <a href="{{url_for('main.user',username=comment.author.username)}}">            <img class="img-rounded profile-thumbnail" src="{{ comment.author.gravatar(size=40) }}">            </a>        </div>        <div class="comment-content">            <div class="comment-data">{{ moment(comment.timestamp).fromNow() }}</div>            <div class="comment-author">                <a href="{{ url_for('main.user',username=comment.author.username) }}">                    {{ comment.author.username }}                </a>            </div>            <div class="comment-body">

和之前首页显示文章的做法基本一样。

然后是disabled变量。经常逛论坛或者微博的朋友都知道,有些评论时违规的,比方说卖片的或者骂人的。作为管理员会把他们给删除或者折叠或者调整为用户不可见。所以所有的comment都有一个disabled属性,来决定这个评论能否公之于众,这个功能在jinja2中实现方法如下:

{% if comment.disabled %}    <p><i>该评论已被删除</i></p>{% endif %}

第二部分会说一下如何管理评论。

原创粉丝点击