程序猿果然是需要精神高度集中才能工作的类型啊......这礼拜生病了。。。看书效率奇低。。。。
上一章节讲完了用户关注的关系
这一章节来讲另外一个大功能,评论功能
由于评论和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 %}---------------------------------------------------------------------------------- 插播结束--------------------------------------------------------------------------------------
来看一下效果图
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。