flask_关注者

表的模型实现

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 %}
View Code

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>

  

 

·

posted @ 2017-08-28 13:17  换季  阅读(189)  评论(0编辑  收藏  举报