表的模型实现

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. 【转】"超时时间已到。在操作完成之前超时时间已过或服务器未响应"的解决方法

    方法有以下三种: 1.原因应该在数据访问有问题,可以把连接时间设置长些,在数据库连接字符串,加上Connect Timeout=18000,单位毫秒 2,在web.config中加上以下语句: < ...

  2. 如何解决Eureka Server不踢出已关停的节点的问题?

    如何解决Eureka Server不踢出已关停的节点的问题? eureka端: eureka.server.enable-self-preservation                       ...

  3. 好吧,不说闲言碎语,不抱怨,好好工作,好好学习,多总结。记录一下昨天做vuejs的心得

    1.做了两个bat文件,一个是直接定位到vuejs项目并且运行,另一个就是打包 run.bat d:cd wwwcd vuecd dtbpmcnpm run devpause build.bat cd ...

  4. dstat工具使用介绍

    一.dstat工具多功能系统资源统计生成工具.获取信息类似top.free.iostat.vmstat等多个工具的合集,所以也称为vmstat.iostat.ifstat等工具替代品,其结果可以存储成 ...

  5. Android商城开发系列(一)——开篇

    最近在看尚硅谷的硅谷商城视频,想系统学习一下Android的商城开发流程,打算跟着视频的一步步做出一个商城,然后写博客总结记录一下整个商城的开发过程以及使用到的技术知识点,这个商城的最终效果如下图所示 ...

  6. UVA 12405 Scarecrow (基础DP)

    题意: 给出一个1*N的矩阵(就是一行的格子),其中部分格子可以有草,部分无草,现在要求放置一些稻草人在某些格子上,每个稻草人可以覆盖3个连续格子,为使得有草的格子都能被覆盖,问最少放置几个稻草人. ...

  7. hdu 2126 Buy the souvenirs 买纪念品(01背包,略变形)

    题意: 给出一些纪念品的价格,先算出手上的钱最多能买多少种东西k,然后求手上的钱能买k种东西的方案数.也就是你想要买最多种东西,而最多种又有多少种组合可选择. 思路: 01背包.显然要先算出手上的钱m ...

  8. 爬取豆瓣电影top250并存储到mysql数据库

    import requests from lxml import etree import re import pymysql import time conn= pymysql.connect(ho ...

  9. UVA1610 PartyGame 聚会游戏(细节题)

    给出一组字符串D,要找一个字符串S使得D中一半小于等于S,另外一半大于S.输入保证一定有解.长度要尽量短,在此基础上字典序尽量小. 分类谈论,细节挺多的,比如'Z'. 其实直接暴就过了,没分类辣么麻烦 ...

  10. ACM博弈论基础

    博弈论的题目有如下特点: 有两名选手 两名选手交替操作,每次一步,每步都在有限的合法集合中选取一种进行 在任何情况下,合法操作只取决于情况本身,与选手无关 游戏败北的条件为:当某位选手需要进行操作时, ...