Flask Web 开发 关注者

学到这1章,感觉有点回到第8章的味道……有几个坑还是后期需要静下心来补的

对模型间的关系,准备另外单独拎出来写1篇测试文章,这里留个位置给链接吧

#

# 留位置给番外篇

#

上图是1个自援用的关系图,就用于像关注和被关注这样,关联表两边只有1个实体(用户)的情况的。

本例的关联表是follows,其中每行都表示1个用户关注了另外一个用户。图中左侧表示的1对多关系把用户和follows 表中的1组记录联系起来,用户是关注者。图中右侧表示
的1对多关系把用户和follows 表中的1组记录联系起来,用户是被关注者。

上面这句话甚么意思呢?

就是在follows表格里面,他的组成情势是2个列,follower_id和followed_id,里面的id分别是主动关注的人的id被关注者的id

class Follow(db.Model):
__tablename__ = 'follows'
follower_id = db.Column(db.Integer, db.ForeignKey('users.id'),primary_key=True)
followed_id = db.Column(db.Integer, db.ForeignKey('users.id'),primary_key=True)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)

从Follow类的属性定义里面我们就可以看到,follower_id作为外键,对应的是users.id, 而followed_id作为外键,对应的也是user.id

再来看对应的users表,也就是User类。

需要特别注意的是foreign_keys的值,

followed表示已关注的人,他对应的是Follow类里面的follower_id这个属性,也就是,关注了哪些人,具体的值是id号

followers表示自己的粉丝,对应的是Follow类里面的followed_id,这个有点拗口,这个实际上是自己粉丝的id

关于lazy,已转载了其他先辈的1篇文章,而关于cascade,是和删除对象时候,关联表格里面的内容会不会1起删掉有关系的,后续再说

class User(UserMixin,db.Model):

#…

followed = db.relationship('Follow',foreign_keys=[Follow.follower_id],
backref=db.backref('follower', lazy='joined'),
lazy='dynamic',cascade='all, delete-orphan')
followers = db.relationship('Follow',foreign_keys=[Follow.followed_id],
backref=db.backref('followed', lazy='joined'),
lazy='dynamic',cascade='all, delete-orphan')

接着是给User实例添加方法

关注的话,你肯定最少要做1个按钮给用户,那这个按钮设计到2个功能,关注和取消关注,2个状态,是不是已关注,是不是已被关注

class User(UserMixin,db.Model):

#…

def follow(self, user):
if not self.is_following(user):
f = Follow(follower=self, followed=user)
db.session.add(f)

def unfollow(self, user):
f = self.followed.filter_by(followed_id=user.id).first()
if f:
db.session.delete(f)

def is_following(self, user):
return self.followed.filter_by(followed_id=user.id).first() is not None

def is_followed_by(self, user):
return self.followers.filter_by(follower_id=user.id).first() is not None

follow() 方法手动把Follow 实例插入关联表,从而把关注者和被关注者联接起来,并让程序有机会设定自定义字段的值。联接在1起的两个用户被手动传入Follow 类的构造器,创建1个Follow 新实例,然后像平常1样,把这个实例对象添加到数据库会话中。注意,这里无需手动设定timestamp 字段,由于定义字段时指定了默许值,即当前日期和时间。unfollow() 方法使用followed 关系找到联接用户和被关注用户的Follow 实例。若要烧毁这两个用户之间的联接,只需删除这个Follow
对象便可。is_following() 方法和is_followed_by() 方法分别在左右两边的1对多关系中搜索指定用户,如果找到了就返回True。

以上文字是书上的,可以看到,follow()方法最后通过db.session.add来插入新对象f,而unfollow()方法则是通过db.session.delete来删除这个实例

分步讲授下,在follow方法内,他通过self.is_following(user)来检查,当前用户针对user是不是已是关注的状态,下面的is_following方法你可以看到,return出来的是not None

也就是说,follow方法在检查结果是not (not None)的情况下,会继续插入新的Follow实例,最后插入数据库

而unfollow方法则是,通过self对象的followed属性查找关注了多少人,然后通过followed_id=user.id这句,找出目前这个user对象并赋予给f

如果f存在,则通过session删除f对象

is_following方法,通过self对象的关注人里面,用user.id来检查自己是不是已关注这个人,返回结果not None,非空

is_followed_by,1样,看self对象自己的粉丝群里面,通过user.id找找是不是有这个人,返回结果也是not None,非空

以上2个方法是表示1个状态,而不是功能性方法。

{% 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">Follow</a>
{% 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 you</span>
{% endif %}

前端渲染写好以后,就要写路由控制了

@main.route('/follow/<username>')
@login_required
@permission_required(Permission.FOLLOW)
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))

@main.route('/unfollow/<username>')
@login_required
@permission_required(Permission.FOLLOW)
def unfollow(username):
user = User.query.filter_by(username=username).first()
if user is None:
flash('Invalid user.')
return redirect(url_for('.index'))
if not current_user.is_following(user):
flash('You are not following this user.')
return redirect(url_for('.user',username=username))
current_user.unfollow(user)
flash('You are now unfollow %s'%username)
return redirect(url_for('.user',username=username))

follow和unfollow为1组

follow的逻辑是:有2个条件,需要已登录状态,需要有FOLLOW权限,通过url里面的username,过滤出该对象用户,随落后行判断

如果用户不存在,则提示flash消息,无功效户

如果用户已关注了该用户,则提示flash消息,已关注该用户

如果没有关注,则履行当前用户的follow方法,关注该用户

unfollow的逻辑1样

@main.route('/followers/<username>')
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.followers.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,follows=follows)

@main.route('/followed-by/<username>')
def followed_by(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.followed.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="Followed by",
endpoint='.followed_by',pagination=pagination,
follows=follows)

随后2个是该用户的粉丝页面和所关注的人的页面

逻辑和上面差不多,也是通过username来过滤出该用户

如果用户没有,则提示flash消息

否则,则进行分页显示你的粉丝队伍和偶像队伍

先来看看整体效果图

点了关注以后的变化

粉丝页面

波比源码 – 精品源码模版分享 | www.bobi11.com
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

波比源码 » Flask Web 开发 关注者

发表评论

Hi, 如果你对这款模板有疑问,可以跟我联系哦!

联系站长
赞助VIP 享更多特权,建议使用 QQ 登录
喜欢我嘛?喜欢就按“ctrl+D”收藏我吧!♡