表的模型实现

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)

 

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')

关注关系的辅助方法

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

 在资料页中显示关注者

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-default">关注</a>
{% else %}
<a href="{{ url_for('.unfollow',username=user.username) }}"
class="btn btn-default">取消关注</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 %}

app/main/views.py: ‘关注’路由和视图函数

@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(u'用户不存在')
return redirect(url_for('.index'))
if current_user.is_following(user):
flash(u'已关注')
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 not following %s anymore.' % username)
return redirect(url_for('.user', username=username))

  

@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('/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)

使用数据库联结查询所关注用户的文章

 要想只查看关注用户的文章需要把posts表和follows表联结起来查询

class User(UserMixin,db.Model):

    #..

    @property
def followed_posts(self):
return Post.query.join(Follow,Follow.followed_id == Post.author_id)\
.filter(Follow.follower_id == self.id)

Post表联结Follow表  Follow表被关注 = 文章作者的id  查找 Follow表中关注者的id

在首页显示所关注用户的文章

app/main/views.py:显示所有博客文章或只显示所关注用户的文章

@main.route('/', methods=['GET', 'POST'])
def index(): #... show_followed=False
if current_user.is_authenticated:
show_followed = bool(request.cookies.get('show_followed',''))
if show_followed:
query = current_user.followed_posts
else:
query = Post.query
pagination = query.order_by(Post.timestamp.desc()).paginate(
page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],
error_out=False)
posts = pagination.items
return render_template('index.html', form=form, posts=posts,show_followed=show_followed,
pagination=pagination)

决定显示所有文章还是只显示所关注用户文章的选项存储在cookie的show_followed字段中,如果其值为非空字符串,则表示只显示所关注用户的文章。

query的值决定最终获取所有博客的查询,或是获取过滤后的博客文章查询

app/main/views.py:查询所有文章还是所关注用户的文章

@main.route('/all')
@login_required
def show_all():
resp = make_response(redirect(url_for('.index')))
resp.set_cookie('show_followed','',max_age=30*24*60*60)
return resp

resp返回一个响应,然后为它的cookie设置为 show_followed为空,过期时间为一个月

@main.route('/followed')
@login_required
def show_followed():
resp = make_response(redirect(url_for('.index')))
resp.set_cookie('show_followed','1',max_age=30*24*60*60)
return resp

resp返回一个响应,然后为它的cookie设置为 show_followed不为空,过期时间为一个月,表示只显示只看所关注用户的文章

接下来改动模板

    <div class="post-tabs">
<ul class="nav nav-tabs">
<li {% if not show_followed %}class="active"{% endif %} ><a href="{{ url_for('.show_all') }}" >全部</a></li>
{% if current_user.is_authenticated %}
<li {% if show_followed %}class="active"{% endif %}><a href="{{ url_for('.show_followed') }}">关注</a> </li>
{% endif %}
</ul>

app/model.py:构建用户时把用户设为自己的关注者

def __init__(self,**kwargs):

    self.follow(self)

app/models.py:把用户设为自己的关注者

    @staticmethod
def add_self_follows():
for user in User.query.all():
if not user.is_following(user):
user.follow(user)
db.session.add(user)
db.session.commit()

  

(venv) >python manage.py shell

>>> User.add_self_follows()

把关注者数量减一

    <a href="{{ url_for('.followers',username=user.username)}}">j
Followers:<span class="badge">{{ user.followers.count() - 1 }}</span>

  

·

flask_关注者的更多相关文章

  1. flask_关注者,联系人和好友

    在这节我们实现的功能比较复杂,就是实现用户"关注"和"取消关注"的功能. 一个用户可以关注多个其他的用户,一个用户也可以被其他多个用户所关注,这样看的话,在数据 ...

  2. 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新3)附高效动态压缩Bitmap

    一.写在前面 爱吖校推如同它的名字一样,是一款校园类信息推送交流平台,这么多的家校互动类软件,你选择了我,这是我的幸运.从第一次在博客园上写博客到现在,我一次一次地提高博文的质量和代码的可读性,都是为 ...

  3. C#开发微信门户及应用(4)--关注用户列表及详细信息管理

    在上个月的对C#开发微信门户及应用做了介绍,写过了几篇的随笔进行分享,由于时间关系,间隔了一段时间没有继续写这个系列的博客了,并不是对这个方面停止了研究,而是继续深入探索这方面的技术,为了更好的应用起 ...

  4. .NET开发人员值得关注的七个开源项目 .

    NET开发人员值得关注的七个开源项目 软近几年在.NET社区开源项目方面投入了相当多的时间和资源,不禁让原本对峙的开源社区阵营大吃一惊,从微软.NET社区中的反应来看,微软.NET开发阵营对开源工具的 ...

  5. [从产品角度学EXCEL 00]-为什么要关注EXCEL的本质

    前言 Hello 大家好,我是尾巴,从今天开始,在这里连载<从产品角度学EXCEL>的系列文章.本文不接受无授权转载,如需转载,请先联系我,非常感谢. 与世面上的大部分EXCEL教程不同的 ...

  6. C# asp.net 搭建微信公众平台(可实现关注消息与消息自动回复)的代码以及我所遇到的问题

    [引言] 利用asp.net搭建微信公众平台的案例并不多,微信官方给的案例是用PHP的,网上能找到的代码很多也是存在着这样那样的问题或者缺少部分方法,无法使用,下面是我依照官方文档写的基于.net 搭 ...

  7. [已招满,谢谢关注]Sogou招聘C#开发人员,有意者请进

    职位名称:c#开发工程师 工作地点:搜狐网络大厦 职责:搜狗商业平台桌面产品 职位要求: 1. 计算机或者相关专业本科或以上学历 2. 精通c#,两年以上实际项目开发经验 3. 熟悉C/S开发架构和设 ...

  8. Worktile协同特色之一:无处不在的关注

    团队沟通中常见问题 在回答这个问题之前,我们不妨先来思考一下,团队成员之间互相配合沟通的几个问题:1. 任务的执行者在完成这个任务时,如何通知到此任务相关联的其他成员,比如该任务的后续任务执行者?2. ...

  9. fir.im Weekly - 除了新 MacBook Pro,近期值得关注的移动开发好资源

    最近,最引人瞩目的莫过于 Apple 产品发布会,MacBook Pro 的更新可能是四年来变化最大的一版.除了更轻.更薄.性能更好.电力更足之外,最大的变化是加入了Touch Bar,被定义为 Ma ...

随机推荐

  1. jquery的$().each和$.each的区别

    在jquery中,遍历对象和数组,经常会用到$().each和$.each(),两个方法.两个方法是有区别的,从而这两个方法在针对不同的操作上,显示了各自的特点. $().each,对于这个方法,在d ...

  2. BeanCopier使用说明

    BeanCopier从名字可以看出了,是一个快捷的bean类复制工具类. 一 如何使用,我就直接丢代码了 public class BeanCopierTest { static SimpleDate ...

  3. js 回车提交表单

    一.整个页面用一个回车提交事件: <input type="button" value="回车提交" id="auto" onclic ...

  4. 韦东山笔记之安装arm-linux-gcc交叉编译环境详细步骤。

    1在关盘主目录tools下复制arm-linux-gcc-3.4.5-glibc-2.3.6.tar.bz2到虚拟机上     解压 tar xjf arm-linux-gcc-3.4.5-glibc ...

  5. JavaScript中var a=b=c=d的发现

    看了别人的博客随手记录下 先看一下以下的代码 var a=1,b=2,c=3; (function(){ var a=b=1; })(); console.log(a); console.log(b) ...

  6. 网络文件系统(NFS)的使用

    一.简介 NFS--Network FileSystem,即网络文件系统,主要功能是让网络上的不同操作系统之间共享数据. 远程服务器端共享出文件或目录,然后远羰共享出来的文件或目录就可通过挂 载的方式 ...

  7. Android Google Map API使用的八个步骤

    本系列教程将分为两部分,第一部分是指导用户使用Mapview控件进行编程,其中包括了如何获得Google Map API,如何使用该API进行简单的开发,如何获得用户当前所在的位置.第二部分则包括如何 ...

  8. 宿主机Windows访问虚拟机Linux文件(一)

    如果用户使用windows操作系统,但是在虚拟机下配置Linux内核操作操作系统,往往需要实现通过宿主机Windows操作系统访问Linux内核操作系统中资源.本次实验实现的是宿主机windows 1 ...

  9. (一)我的Javascript系列:Javascript的面向对象旅程(上)

    今宵酒醒何处,杨柳岸,晓风残月 导引 我的JavaScript系列文章是我自己对JavaScript语言的感悟所撰写的系列文章.现在还没有写完.目前一共出了下面的系列: (三)我的JavaScript ...

  10. vuex的state,mutation,getter,action

    开始!正常的简单的拆分下是这样的文件当然module可以在store下面新建一个文件夹用来处理单独模块的vuex管理比较合适. 1.index.js下面 import Vue from 'vue' i ...