如果用户查看一个尚未关注用户的资料页,页面中要显示一个“Follow”(关注)按钮,如果查看已关注用户的资料则显示“Unfollow”(取消关注)按钮,并且,页面中最好能显示出关注者和被关注者的数量,再列出关注和被关注者的用户列表,并在相应的用户资料页中显示“Follow You”(关注了你)标志,对用户资料页模板的改动如下例所示:
# app/templates/user.html
#...
{% if current_user.can(Permission.FOLLOW) and user != current_user %}
{% if not current_user.is_following(user) %}
<a href="{{ url-for('.follow', username=user.username) }}"
class="btn btn-primary">Followa>
{% else %}
<a href="{{ url_for'.unfollow', username = user.username) }}"
class="btn btn-default">Unfollow
a>
{% endif %}
{% endif %}
<a href="{{ url_for('.followers', username=user.username) }}">
Followers:<span class='badge'>{{ user.followers.count() }}span>
a>
<a href="{{ url_for(.followed_by, username=user.username) }}">
Following:<span class="badge">{{ user.followed.count() }}span>
a>
{% if current_user.is_authenticated() and user != current_user and user.is_following(current_user) %}
| <span class="label label-default">Follows youspan>
{% endif %}
这次修改模板用到了4个新端点,用户在其他用户的资料页中点击”Follow”(关注)按钮后,执行的是/follow/路由,这个路由的实现方法如下:
# app/main/views.py
#...
@main.route('/follow/')
@login_required
@permission_required
def follow(username):
user = User.query.filter_by(username=username).first()
if user is None:
flash('Invalid user.')
return redirect(url_for('.index'))
if current_user.is_following(user):
flash('You are already following this user.')
return redirect(url_for('.user',username=username))
current_user.follow(user)
flash('You are now following %s.' % username)
return redirect(url_for('.user',username=username))
这个视图函数先加载请求的用户,确保用户存在且当前登录用户还没有关注这个用户,然后调用User模型中定义的辅助方法follow()
,用以联接两个用户 /unfollow/
路由的实现方式类似
用户在其他用户的资料页中点击关注者数量后,将调用/followers/
路由,这个路由的实现如下所示:
# app/main/views.py
# ...
@main.route('/followers/')
def followers(username):
user = User.query.filter_by(username=username).first()
if user is None:
flash('Invalid user.')
return redirect(url_for('.index'))
page = request.args.get('page', 1, type=int)
pagination = user.follower.paginate(
page, per_page=current_app.config['FLASKY_FOLLOWERS_PER_PAGE'],
error_out=False)
follows = [{'user': item.follower, 'timestamp':item.timestamp}
for item in pagination.items]
return render_template('followers.html', user=user, title='Followers of',
endpoint = '.followers', pagination=pagination,
followers=followers)
这个函数加载并验证请求的用户,然后使用之前介绍的技术分页显示该用户的followers关系,由于查询关注者返回的是Follow实例列表,为了渲染方便,我们将其转换成一个新列表,列表中的各元素都包含user
和timestamp
字段
渲染关注者列表的模板可以写的通用一些,以便能用来渲染关注的用户列表和被关注的用户列表,模板接受的参数包括用户对象、分页链接使用的端点、分页对象和查询结果列表
followed_by
端点的实现过程几乎一样,唯一的区别在于:用户列表从user.followed
关系中获取,传入的模板的参数也要进行响应调整
followers.html
模板使用两列表格实现,左边一列用于显示用户名和头像,右边一列用于显示Flask-Moment时间戳