进入新的一章节了
又是一个比较大的功能,写博客
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer,primary_key = True)
body = db.Column(db.Text) #文章内容
timestamp = db.Column(db.DateTime,index = True, default = datetime.utcnow) #时间戳,据现在多久
author_id = db.Column(db.Integer,db.ForeignKey('users.id')) #外键,和users表相连
既然Post类里有外键,那么,User类里面必定有相连接的属性,如下
class User(UserMixin, db.Model):
# ...
posts = db.relationship('Post', backref='author', lazy='dynamic') #和Post类相连接的桥梁
写文章的地方,放在主页,设置一个表单,让客户可以输入内容
那就新建一个form
class PostForm(Form):
body = TextAreaField("What's on your mind?", validators=[Required()])
submit = SubmitField('Submit')
既然是要在主页上显示表单,那么,主页的内容势必要做修改了
@main.route('/', methods=['GET', 'POST'])
def index():
form = PostForm()
if current_user.can(Permission.WRITE_ARTICLES) and \ #检查用户是否有写文章权限
form.validate_on_submit():
post = Post(body=form.body.data, #将文章内容生成post实例
author=current_user._get_current_object())
db.session.add(post)
return redirect(url_for('.index'))
posts = Post.query.order_by(Post.timestamp.desc()).all() #posts代表所有写过的文章,按照文章降序排列
return render_template('index.html', form=form, posts=posts)
这里的current_user._get_current_object()的用法,是提取真正的对象
其实current_user只是一个代理包装后的对象,而这里数据库需要的是真正的对象
不是理解特别深,不过这个方法指导如何使用了。
逻辑部分改完,就要改显示的模板部分了
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Flasky{% endblock %}
{% block page_content %}
{% block scripts %} <!-- 记得引入moment扩展 -->
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
...
<div>
{% if current_user.can(Permission.WRITE_ARTICLES) %}
{{ wtf.quick_form(form) }}
{% endif %}
</div>
<ul class = "posts">
{% for post in posts %} <!-- 历遍所有的posts -->
<li class = "post">
<div class="profile-thumbnail">
<a href = "{{ url_for('.user',username = post.author.username) }}"> <!--图片做超链接,目标用户页面-->
<img class = "img-rounded profile-thumbnail"
src = "{{ post.author.gravatar(size = 40) }}"> <!-- 图片来源于gravatar -->
</a>
</div>
<div class="post-date">{{ moment(post.timestamp).fromNow() }}</div>
<div class="post-author">
<a href = "{{ url_for('.user',username = post.author.username) }}"> <!-- 点击名字也导向用户页面 -->
{{ post.author.username }}
</a>
</div>
<div class = "post-body">{{ post.body }}</div> <!-- 文章内容 -->
</li>
{% endfor %}
</ul>
{% endblock %}
效果图如下。
----------------------------------------------------------------------------功能分割线--------------------------------------------------------------------------------------
除了在主页看到所有人的留言之外,我们还需要在个人主页看到该用户自己所有的博客文章
那我们势必要在user.html页面内修改内容
其实,2个模板块里面调用的对象都是一样的,都是posts,所以我们可以统一化管理,将这部分调用功能单独做出来做成一个html文件
posts = Post.query.order_by(Post.timestamp.desc()).all() #找Post类里面的所有内容
posts = user.posts.order_by(Post.timestamp.desc()).all() #找当前用户的posts属性(对应Post类里面的所有博客)
所以,我们在user类里面通过下面的方法引入 _posts.html 内容,其实这个和extends功能感觉有异曲同工的味道
另外,同时在index.html里面用到这部分的,也要引用这个功能模板
<ul class = "posts">
{% for post in posts %}
<li class = "post">
<div class="profile-thumbnail">
<a href = "{{ url_for('.user',username = post.author.username) }}">
<img class = "img-rounded profile-thumbnail"
src = "{{ post.author.gravatar(size = 40) }}">
</a>
</div>
<div class="post-date">{{ moment(post.timestamp).fromNow() }}</div>
<div class="post-author">
<a href = "{{ url_for('.user',username = post.author.username) }}">
{{ post.author.username }}
</a>
</div>
<div class = "post-body">{{ post.body }}</div>
</li>
{% endfor %}
</ul>
在user.html里面
使用下面语句来引入
<h3>Posts by {{ user.username }}</h3>
{% include "_posts.html" %}
注意,_posts.html 模板名的下划线前缀不是必须使用的,这只是一种习惯用法,以区分独立模板和局部模板。
效果图如下