Flask Web 开发 用户评论


程序猿果然是需要精神高度集中才能工作的类型啊......这礼拜生病了。。。看书效率奇低。。。。


上一章节讲完了用户关注的关系

这一章节来讲另外一个大功能,评论功能

由于评论和2个模型有关系,分别是谁发了评论,以及评论了哪个文章,所以这次又要更新数据库模型了




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.DateTime , index = True , default = datetime.utcnow)
	disabled = db.Column(db.Boolean)
	author_id = db.Column(db.Integer , db.ForeignKey('users.id'))
	post_id = db.Column(db.Integer , db.ForeignKey('users.id'))
	
	@staticmethod
	def on_changed_body(target,value,oldvalue,initiator):
		allowed_tags = ['a', 'abbr', 'acronym', 'b', 'code', 'em', 'i','strong']
		target.body_html = bleach.linkify(bleach.clean(markdown(value, output_format='html'),
							tags=allowed_tags, strip=True))
db.event.listen(Comment.body, 'set', Comment.on_changed_body)

这个Comment和Post基本上一致,不过多了一个disabled属性,书上写是给管理员用的。


既然Comment里面设置了2个外键,那么User和Post里面也要设置相应的关系

class User(db.Model):
# ...
comments = db.relationship('Comment', backref='author', lazy='dynamic')


class Post(db.Model):
# ...
comments = db.relationship('Comment', backref='post', lazy='dynamic')


另外,在post界面,需要一个表单界面给用户输入评论

class CommentForm(Form):
	body = StringField('',validators=[Required()])
	submit = SubmitField('Submit')


接下来要讲一个比较重要的部分,到目前为止没有搞懂,准备晚上去stackoverflow上面问去

@main.route('/post/<int:id>')
def post(id):
	post = Post.query.get_or_404(id)
	form = CommentForm()
	if form.validate_on_submit():
		comment = Comment(body = form.body.data, post = post, author = current_user._get_current_object())
		db.session.add(comment)
		flash('Your comment has been published.')
		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)//current_app.config['FLASKY_COMMENTS_PER_PAGE']+1
		pagination = post.comments.order_by(Comment.timestamp.asc()).paginate(
			page,per_page = current_app.config['FLASKY_COMMENTS_PER_PAGE'],
			error_out = False)
		comments = pagination.items
	return render_template('post.html',posts=[post],form = form,comments=comments,pagination = pagination)

这里,当你发表评论以后,他会进行重定向到post页面,并且在request请求里面,将page设置成-1,这个 -1 实际上是作为特殊功能来使用

什么特殊功能呢?就是当你的请求中page=-1的时候,网站就等于明白你刚发了评论,而一般发完评论,用户习惯总是看到最后页自己的评论,下面的分页显示的页面,会直接显示到最后一页,page = (post.comments.count()-1)//current_app.config['FLASKY_COMMENTS_PER_PAGE']+1 这句话的逻辑功能,就是计算出最后一页的页数

只不过我到现在没明白,他为什么要把comments的总数减去1

另外,书上的除法用了/ ,我想了半天应该是//啊,不然有小数点怎么用,去github一看作者的源码。。。。果然。。。是//,PYTHON3的新除法

哈哈,算是抓了书本一个BUG


然后做一个_comments.html的模板,用来渲染评论列表,和post的相类似,不过这个html需要加入到post.html里面去,作用是在在post页面的每个博客文章下面,加上评论列表

注意,这里渲染的页面是post.html页面,所以,这个页面是此篇博客文章的单篇文章的页面,所以,直接可以在include _posts.html下面include _comments.html

所以实际上post和comment是2部分拼接起来的

<ul class="comments">
    {% for comment in comments %}
    <li class="comment">
        <div class="comment-thumbnail">
            <a href="{{ url_for('.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-date">{{ moment(comment.timestamp).fromNow() }}</div>
            <div class="comment-author"><a href="{{ url_for('.user', username=comment.author.username) }}">{{ comment.author.username }}</a></div>
            <div class="comment-body">
                {% if comment.body_html %}
                    {{ comment.body_html | safe }}
                {% else %}
                    {{ comment.body }}
                {% endif %}
            </div>
        </div>
    </li>
    {% endfor %}
</ul>

然后,要在主页和用户页面可以这些可以看到用户所发博客的地方,给所有博客加一个comment按钮

,因为要统一渲染,所以,就加在了 _posts.html 里面

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


这样,除了edit,Permalink,之外,还会多出一个comments的按钮

然后url地址后面有个#comments的URL片段,关于URL片段下面有讲解

---------------------------------------------------------------------------插播URL片段的知识------------------------------------------------------------------------------

上面加在 _posts.html里面的这段话,你可以看到,在url地址后面,加了一个 #comments

这个叫做URL片段,什么意思呢?

可以理解为:#这个符号,在URL地址里面相当于分隔符

#左边的,代表真实URL,对外的,就是普通用户可以看到的URL

#右边的,代表对网页内部的代码,你在浏览器的地址栏是看不到的,他针对的是,当前页面HTML文件内,id=comments的内容

具体作用是:当加载这个页面时,直接会将这个id处于的位置,滚到页面顶端

类似于我们平时的用户体验是:当你评论完以后,页面重新加载,评论区域会自动翻滚到你的页面最上端,体验很好。


这里转2个其他前辈写的文章,可以参考下,写得不错。尤其是第一篇,他用浏览器调试界面的一些例子,详细地讲解了#后面的其实可以算是隐藏符号这一特性。

http://www.cnblogs.com/ublue/articles/4471210.html

https://www.oschina.net/translate/what-every-web-developer-must-know-about-url-encoding


比如在这个例子里面,他的#comments,针对的就是post.html这个主页面里面的  <h4 id="comments">Comments</h4>

整体post代码见下面

我理解,这样的作用是,按了comments按钮以后,可以直接跳转到post页面的评论区域,等于是个页中页功能。

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Flasky - Post{% endblock %}

{% block page_content %}
{% include '_posts.html' %}
<h4 id="comments">Comments</h4>
{% if current_user.can(Permission.COMMENT) %}
<div class="comment-form">
    {{ wtf.quick_form(form) }}
</div>
{% endif %}

{% include '_comments.html' %}
{% if pagination %}
<div class="pagination">
    {{ macros.pagination_widget(pagination, '.post', fragment='#comments', id=posts[0].id) }}
</div>
{% endif %}
{% endblock %}
---------------------------------------------------------------------------------- 插播结束--------------------------------------------------------------------------------------

来看一下效果图










智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告