Flask Web 开发 关注者

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

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

#

# 留位置给番外篇

#

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

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

的一对多关系把用户和follows 表中的一组记录联系起来,用户是被关注者。

上面这句话什么意思呢?

就是在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,已经转载了其他前辈的一篇文章,而关于cascade,是和删除对象时候,关联表格里面的内容会不会一起删掉有关系的,后续再说

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实例添加方法

关注的话,你肯定起码要做一个按钮给用户,那这个按钮设计到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 实例插入关联表,从而把关注者和被关注者联接起来,并让程序有机会设定自定义字段的值。联接在一起的两个用户被手动传入Follow 类的构造器,创建一个Follow 新实例,然后像往常一样,把这个实例对象添加到数据库会话中。注意,这里无需手动设定timestamp 字段,因为定义字段时指定了默认值,即当前日期和时间。unfollow() 方法使用followed 关系找到联接用户和被关注用户的Follow 实例。若要销毁这两个用户之间的联接,只需删除这个Follow
对象即可。is_following() 方法和is_followed_by() 方法分别在左右两边的一对多关系中搜索指定用户,如果找到了就返回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,一样,看self对象自己的粉丝群里面,通过user.id找找是否有这个人,返回结果也是not None,非空

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

{% 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为一组

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

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

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

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

unfollow的逻辑一样

@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消息

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

先来看看整体效果图

点了关注以后的变化

粉丝页面



时间: 2024-10-29 19:09:47

Flask Web 开发 关注者的相关文章

Flask之旅《Flask Web开发:基于Python的Web应用开发实战》学习笔记

<Flask Web开发:基于Python的Web应用开发实战> 点击上方的"目录"快速到达哦! 虽然简单的网站(Flask+Python+SAE)已经上线,但只是入门.开发大型网站,系统地学习一遍还是有必要的. 1 虚拟环境 2016-6-8 书上介绍了 virtualenv,每个venv都会拷贝一份packages到项目 /venv目录. virtualenv venv venv\Scripts\activate.bat (venv) $ pip freeze >

flask web开发笔记 -- 数据库

关系数据库基于关系,有主键.外键等.它存储数据高效,避免了重复:修改数据方便.缺点是连接的成本过高. NoSQL尽量避免连接,但是增加了数据冗余,修改数据麻烦,不过查询快速. 对于中小型的应用,两者的效率差别不大. python数据库框架 Flask对数据库没有限制,你可以使用MySQL, Postgres, SQLite, Redis, MongoDB或CouchDB等.另外还有数据抽象层SQLAlchemy和MongoEngine等. 选择数据库时需要关注: 易用性:抽象层,比如ORM(ob

《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(下)

目录 前言 第8章 用户认证 第9章 用户角色 第10章 用户资料 第11章 博客文章 第12章 关注者 第13章 用户评论 第14章 应用编程接口   前言 第1章-第7章学习实践记录请参见:<Flask Web开发——基于Python的Web应用开发实践>一字一句上机实践(上) 本文记录自己学习<Flask Web开发——基于Python的Web应用开发实践>的第8章-第14章内容.相比于刚开始学习第1-7章内容来说,本部分内容实战性更强,而且在书本上遇到的问题也相对较少,如果

《Flask Web开发:基于Python的Web应用开发实战》pdf 免费下载

<Flask Web开发:基于Python的Web应用开发实战>pdf 免费下载链接: https://u253469.ctfile.com/fs/253469-292665036 第一部分 Flask 简介第1 章 安装 .........................................................................................................................................

Flask web开发----使用mysql数据库

根据<flask web开发>书中说不建议在生产环境中使用SQLite,所以在我跟着书本敲完api这一章的代码时,准备将数据库改用成mysql 1.现将这俩个文件删除,因为这是之前使用的SQLite数据库相关的文件 2.将原项目中的config文件中数据库的地址修改为如图所示的Mysql数据库.你需要现在你本机电脑上安装Mysql数据库,而且你存在一个用户的账户为:root,密码为:root,创建的数据库名称为Flask.(这里对mysql不做过多的讲解) 出于安全考虑可以将路径通过 (ven

flask web开发笔记 -- 快速入门

flask web开发笔记 -- 快速入门 初始化 Flask应用需要创建应用实例. Web服务器通过Web Server Gateway Interface (WSGI)协议把从客户端接收到的请求传递给该对象.应用程序实例是Flask类对象,通常创建如下: from flask import Flask app = Flask(__name__) Flask类的构造函数唯一的参数是应用的主模块名或包名,用于确定应用的根目录.对于大多数应用程序,使用Python的__name__变量即可. 路由

flask web开发笔记 -- 表单 --待整理

虽然Flask的请求对象给表单处理提供了足够的支持,但也有一些任务繁琐和重复.比如为表单生成HTML代码和验证提交表单数据. Flask-WTF扩展能解决上述问题.它基于wtforms 防止跨站请求伪造 跨站请求伪造(Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法.跟跨网站脚本(XSS)相比,XSS

《Flask Web开发:基于Python的Web应用开发实战》pdf 完整版免费下载

<Flask Web开发:基于Python的Web应用开发实战>.pdf pdf 完整版免费下载: https://u253469.ctfile.com/fs/253469-292665036 更多电子书下载: http://hadoopall.com/book 内容简介 本书不仅适合初级Web开发人员学习阅读,更是Python程序员用来学习高级Web开发技术的优秀参考书. ? 学习Flask应用的基本结构,编写示例应用: ? 使用必备的组件,包括模板.数据库.Web表单和电子邮件支持: ?

Flask Web开发入门北京快乐8出售之文件上传

本章北京快乐8出售 dsluntan.com 我们介绍Flask Web开发中涉及的文件上传模块 定义后台接收处理逻辑@app.route('/upload', methods=['POST'])def upload_file():if request.method == 'POST': check if the post request has the file part if 'file' not in request.files: logger.debug('No file part')