一、用户信息页
1、创建视图函数(microblog.py)
1 @app.route('/user/<nickname>') 2 @login_required 3 def user(nickname): 4 user =model.User.query.filter_by(nickname = nickname).first() 5 if user == None: 6 flash('User ' + nickname + ' not found.') 7 return redirect(url_for('index')) 8 posts = [ 9 { 'author': user, 'body': 'Test post #1' }, 10 { 'author': user, 'body': 'Test post #2' } 11 ] 12 return render_template('user.html', 13 user = user, 14 posts = posts)
(1)我们在这个视图函数里所用的路由装饰器和前面的不同,我们加入了一个参数进去<nickname>,这转化为一个同名的参数添加到视图函数。
(2)我们接受到nickname参数从数据库加载用户,如果没有用户抛出错误信息,重定向到首页。
(3)这里在posts中,author都是user,说明在用回信息页上只能显示自己的blog
2.创建用户模板(templates/user.html)
1 {% extends "base.html" %} 2 {% block content %} 3 <h1>User:{{user.nickname}}</h1> 14 <hr> 15 {% for post in posts %} 16 {{post.author.nickname}}says:<b>{{post.body}}</b> 17 {% endfor %} 18 {% endblock %}
3.在导航栏里添加用户信息页的连接(base.html)
10 <div>Microblog: 11 <a href="{{ url_for('index') }}">Home</a> 12 {% if g.user.is_authenticated() %} 13 |<a href="{{ url_for('user',nickname=g.user.nickname) }}">Your Profile</a> 14 | <a href="{{ url_for('logout') }}">Logout</a> 15 {% endif %} 16 </div>
二、头像
1.这里我们没有采用教程上的gravatar来获取用户头像,我们使用的是本地图片(model.py)
1 class User(db.Model): 2 id = db.Column(db.Integer, primary_key = True) 3 nickname = db.Column(db.String(64), unique = True) 4 email = db.Column(db.String(120), unique = True) 5 posts = db.relationship('Post', backref = 'author', lazy = 'dynamic') 6 about_me = db.Column(db.String(140)) 7 last_seen = db.Column(db.DateTime) 8 def is_authenticated(self): 9 return True 10 def is_active(self): 11 return True 12 def is_anonymous(self): 13 return False 14 def avatars(self): 16 return sep + 'static' + sep + 'img' + sep + '1.jpg' 17 def get_id(self): 18 try: 19 return unicode(self.id) # python 2 20 except NameError: 21 return str(self.id) # python 3 22 def __repr__(self): 23 return '<User %r>' % (self.nickname)
2.将头像显示在用户信息页中(user.html)
1 {% extends "base.html" %} 2 {% block content %} 3 <table> 4 <tr valign="top"> 5 <td><img src="{{user.avatars()}}" style="128px;height: 128px"></td> 6 <td><h1>User: {{user.nickname}}</h1></td> 12 </tr> 13 </table> 14 <hr> 15 {% for post in posts %} 16 {{post.author.nickname}}says:<b>{{post.body}}</b>
17 {% endfor %}
18 {% endblock %}
User 类负责返回头像是一个很巧妙的事情,如果有一天决定不想要 Gravatar 头像,我们只要重构 avatar 返回不同的 URLs(即使指向我们自己的服务器,如果我们想要自己的头像服务器),所有我们的模版将会自动地开始显示新的头像。
3.在每一个blog前面也显示用户头像(user.html)
1 {% for post in posts %} 2 <table> 3 <tr valign="top"> 4 <td><img src="{{post.author.avatar(50)}}"></td><td><i>{{post.author.nickname}} says:</i><br>{{post.body}}</td> 5 </tr> 6 </table> 7 {% endfor %}
4.下面我们通过运行来展示下效果
三、在子模板中重用
我们已经实现了用户信息页,它能够显示用户的 blog。我们的首页也应该显示任何一个用户这个时候的 blog 。这样我们有两个页需要显示用户的 blog。当然我们可以直接拷贝和复制处理渲染 blog 的模板,但这不是最理想的。因为当我们决定要修改 blog 的布局的时候,我们要更新所有使用它的模板。相反,我们将要制作一个渲染 blog 的子模板,我们在使用它的模板中包含这个子模板。我们创建一个 blog 的子模板(templates/post.html)
1 table> 2 <tr valign="top"> 3 <td><img src="{{post.author.avatars()}}" style=" 50px;height: 50px"></td><td><i>{{post.author.nickname}} says:</i><br>{{post.body}}</td> 4 </tr> 5 </table>
接着我们使用 Jinja2 的 include 命令在我们的用户模板中调用这个子模板(文件templates/user.html):
1 {% for post in posts %} 2 {% include 'post.html' %} 3 {% endfor %}
一旦我们有一个功能上完全实现的首页,我们将会调用这个子模板,但是现在不准备这么做,将会把它留在后面的章节。
四、添加用户简介以及每个用户访问页面的最后一次的时间在用户信息页上
1.修改数据库,user表中增加两个字段(about_me,last_seen)(model.py)
1 class User(db.Model): 2 id = db.Column(db.Integer, primary_key = True) 3 nickname = db.Column(db.String(64), unique = True) 4 email = db.Column(db.String(120), unique = True) 5 posts = db.relationship('Post', backref = 'author', lazy = 'dynamic') 6 about_me = db.Column(db.String(140)) 7 last_seen = db.Column(db.DateTime) 8 def is_authenticated(self): 9 return True 10 def is_active(self): 11 return True 12 def is_anonymous(self): 13 return False 14 def avatars(self):16 return sep + 'static' + sep + 'img' + sep + '1.jpg' 17 def get_id(self): 18 try: 19 return unicode(self.id) # python 2 20 except NameError: 21 return str(self.id) # python 3 22 def __repr__(self): 23 return '<User %r>' % (self.nickname)
2.运行迁移数据库脚本:python db_migrate.py
3.修改用户信息页:(user.html)
1 <tr valign="top"> 2 <td><img src="{{user.avatars()}}" style="128px;height: 128px"></td> 3 <td> 4 <h1>User: {{user.nickname}}</h1> 5 {% if user.about_me %}<p>{{user.about_me}}</p>{% endif %} 6 {% if user.last_seen %}<p><i>Last seen on: {{user.last_seen}}</i></p>{% endif %}8 </td> 9</tr>
注:我们利用 Jinja2 的条件语句来显示这些字段,因为只有当它们被设置的时候才会显示出来。
4.修改before_request函数,在数据库中更新用户最后一次访问的时间(microblog.py)
1 @app.before_request 2 def before_request(): 3 from model import db 4 g.user = current_user 5 if g.user.is_authenticated(): 6 g.user.last_seen = datetime.utcnow() 7 db.session.add(g.user) 8 db.session.commit()
如果你登录到你的信息页,最后出现时间会显示出来。每次刷新页面,最后出现时间都会更新,因此每次浏览器在发送请求之前,before_request 函数都会在数据库中更新时间。
五、编辑用户信息
1.添加一个编辑用户信息的表单(form.py)
1 # encoding=utf8 2 from flask_wtf import Form 3 from wtforms import StringField, BooleanField,TextAreaField 4 from wtforms.validators import DataRequired ,length #简单地检查相应域提交的数据是否是空 5 class EditForm(Form): 6 nickname = StringField('nickname', validators=[DataRequired()]) 7 about_me = TextAreaField('about_me', validators=[length(min=0, max=140)])
2添加模板(templates/edit.html)
1 <!-- extend base layout --> 2 {% extends "base.html" %} 3 4 {% block content %} 5 <h1>Edit Your Profile</h1> 6 <form action="" method="post" name="edit"> 7 {{form.hidden_tag()}} 8 <table> 9 <tr> 10 <td>Your nickname:</td> 11 <td>{{form.nickname(size = 24)}}</td> 12 </tr> 13 <tr> 14 <td>About yourself:</td> 15 <td>{{form.about_me(cols = 32, rows = 4)}}</td> 16 </tr> 17 <tr> 18 <td></td> 19 <td><input type="submit" value="Save Changes"></td> 20 </tr> 21 </table> 22 </form> 23 {% endblock %}
3.编写视图函数(microblog.py)
1 @app.route('/edit', methods=['GET', 'POST']) 2 @login_required 3 def edit(): 4 from model import db 5 form = EditForm() 6 if form.validate_on_submit(): 7 g.user.nickname = form.nickname.data 8 g.user.about_me = form.about_me.data 9 db.session.add(g.user) 10 db.session.commit() 11 flash('Your changes have been saved.') 12 return redirect(url_for('edit')) 13 else: 14 form.nickname.data = g.user.nickname 15 form.about_me.data = g.user.about_me 16 return render_template('edit.html', form=form)
4.我们在用户信息页上添加一个编辑页的连接
1 <tr valign="top"> 2 <td><img src="{{user.avatars()}}" style="128px;height: 128px"></td> 3 <td> 4 <h1>User: {{user.nickname}}</h1> 5 {% if user.about_me %}<p>{{user.about_me}}</p>{% endif %} 6 {% if user.last_seen %}<p><i>Last seen on: {{user.last_seen}}</i></p>{% endif %} 7 {% if user.id == g.user.id %}<p><a href="{{url_for('edit')}}">Edit</a></p>{% endif %} 8 </td> 9 </tr>
5.运行程序在浏览器中显示: