Flask Vue.js全栈开发|第13章:喜欢文章

  • 原创
  • Madman
  • /
  • 2018-11-26 14:28
  • /
  • 0
  • 73 次阅读

flask vuejs 全栈开发-min.png

Synopsis: 用户在浏览别人发布的文章时,可以将中意的文章添加到自己的 喜欢列表 中,以便于以后查看。同时,会发送动态通知给文章的作者,提醒有新用户喜欢了他的文章

代码已上传到 https://github.com/wangy8961/flask-vuejs-madblog/tree/v0.13 ,欢迎star

1 喜欢文章的用户列表

1. 数据库模型

用户收藏别人的文章,跟用户点赞别人的评论原理是完全一样的,所以是 多对多 关系

修改 back-end/app/models.py

# 喜欢文章
posts_likes = db.Table(
    'posts_likes',
    db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
    db.Column('post_id', db.Integer, db.ForeignKey('posts.id')),
    db.Column('timestamp', db.DateTime, default=datetime.utcnow)
)


class User(PaginatedAPIMixin, db.Model):
    ...
    # 用户最后一次查看 收到的文章被喜欢 页面的时间,用来判断哪些喜欢是新的
    last_posts_likes_read_time = db.Column(db.DateTime)
    ...

    def new_posts_likes(self):
        '''用户收到的文章被喜欢的新计数'''
        last_read_time = self.last_posts_likes_read_time or datetime(1900, 1, 1)
        # 当前用户发布的文章当中,哪些文章被喜欢了
        posts = self.posts.join(posts_likes).all()
        # 新的喜欢记录计数
        new_likes_count = 0
        for p in posts:
            # 获取喜欢时间
            for u in p.likers:
                if u != self:  # 用户自己喜欢自己的文章不需要被通知
                    res = db.engine.execute("select * from posts_likes where user_id={} and post_id={}".format(u.id, p.id))
                    timestamp = datetime.strptime(list(res)[0][2], '%Y-%m-%d %H:%M:%S.%f')
                    # 判断本条喜欢记录是否为新的
                    if timestamp > last_read_time:
                        new_likes_count += 1
        return new_likes_count


class Post(PaginatedAPIMixin, db.Model):
    ...
    # 博客文章与喜欢/收藏它的人是多对多关系
    likers = db.relationship('User', secondary=posts_likes, backref=db.backref('liked_posts', lazy='dynamic'))
    ...

    def is_liked_by(self, user):
        '''判断用户 user 是否已经收藏过该文章'''
        return user in self.likers

    def liked_by(self, user):
        '''收藏'''
        if not self.is_liked_by(user):
            self.likers.append(user)

    def unliked_by(self, user):
        '''取消收藏'''
        if self.is_liked_by(user):
            self.likers.remove(user)

数据库迁移:

(venv) D:\python-code\flask-vuejs-madblog\back-end>flask db migrate -m "user likes posts of other"
(venv) D:\python-code\flask-vuejs-madblog\back-end>flask db upgrade

2. API

修改 back-end/app/api/posts.py

2.1 Like Post

@bp.route('/posts/<int:id>/like', methods=['GET'])
@token_auth.login_required
def like_post(id):
    '''喜欢文章'''
    post = Post.query.get_or_404(id)
    post.liked_by(g.current_user)
    db.session.add(post)
    # 切记要先提交,先添加喜欢记录到数据库,因为 new_posts_likes() 会查询 posts_likes 关联表
    db.session.commit()
    # 给文章作者发送新喜欢通知
    post.author.add_notification('unread_posts_likes_count',
                                 post.author.new_posts_likes())
    db.session.commit()
    return jsonify({
        'status': 'success',
        'message': 'You are now liking this post.'
    })

2.2 Unlike Post

@bp.route('/posts/<int:id>/unlike', methods=['GET'])
@token_auth.login_required
def unlike_post(id):
    '''取消喜欢文章'''
    post = Post.query.get_or_404(id)
    post.unliked_by(g.current_user)
    db.session.add(post)
    # 切记要先提交,先添加喜欢记录到数据库,因为 new_posts_likes() 会查询 posts_likes 关联表
    db.session.commit()
    # 给文章作者发送新喜欢通知(需要自动减1)
    post.author.add_notification('unread_posts_likes_count',
                                 post.author.new_posts_likes())
    db.session.commit()
    return jsonify({
        'status': 'success',
        'message': 'You are not liking this post anymore.'
    })

3. 喜欢文章

在用户文章详情页末尾,有一个 喜欢 按钮,用户点击后就可以喜欢该文章,文章的作者会收到动态通知,谁在什么时候喜欢了他的哪一篇文章,同时用户也可以到他的 已喜欢的文章 中查看历史喜欢过的文章列表

3.1 谁喜欢了你的文章

@bp.route('/users/<int:id>/recived-posts-likes/', methods=['GET'])
@token_auth.login_required
def get_user_recived_posts_likes(id):
    '''返回该用户收到的文章喜欢'''
    user = User.query.get_or_404(id)
    if g.current_user != user:
        return error_response(403)
    page = request.args.get('page', 1, type=int)
    per_page = min(
        request.args.get(
            'per_page', current_app.config['POSTS_PER_PAGE'], type=int), 100)
    # 用户哪些文章被喜欢/收藏了,分页
    posts = user.posts.join(posts_likes).paginate(page, per_page)
    # 喜欢记录
    records = {
        'items': [],
        '_meta': {
            'page': page,
            'per_page': per_page,
            'total_pages': posts.pages,
            'total_items': posts.total
        },
        '_links': {
            'self': url_for('api.get_user_recived_posts_likes', page=page, per_page=per_page, id=id),
            'next': url_for('api.get_user_recived_posts_likes', page=page + 1, per_page=per_page, id=id) if posts.has_next else None,
            'prev': url_for('api.get_user_recived_posts_likes', page=page - 1, per_page=per_page, id=id) if posts.has_prev else None
        }
    }
    for p in posts.items:
        # 重组数据,变成: (谁) (什么时间) 喜欢了你的 (哪篇文章)
        for u in p.likers:
            if u != user:  # 用户自己喜欢自己的文章不需要被通知
                data = {}
                data['user'] = u.to_dict()
                data['post'] = p.to_dict()
                # 获取喜欢时间
                res = db.engine.execute("select * from posts_likes where user_id={} and post_id={}".format(u.id, p.id))
                data['timestamp'] = datetime.strptime(list(res)[0][2], '%Y-%m-%d %H:%M:%S.%f')
                # 标记本条喜欢记录是否为新的
                last_read_time = user.last_posts_likes_read_time or datetime(1900, 1, 1)
                if data['timestamp'] > last_read_time:
                    data['is_new'] = True
                records['items'].append(data)
    # 按 timestamp 排序一个字典列表(倒序,最新喜欢的人在最前面)
    records['items'] = sorted(records['items'], key=itemgetter('timestamp'), reverse=True)
    # 更新 last_posts_likes_read_time 属性值
    user.last_posts_likes_read_time = datetime.utcnow()
    # 将新喜欢通知的计数归零
    user.add_notification('unread_posts_likes_count', 0)
    db.session.commit()
    return jsonify(records)

3.2 你喜欢的文章

@bp.route('/users/<int:id>/liked-posts/', methods=['GET'])
@token_auth.login_required
def get_user_liked_posts(id):
    '''返回该用户喜欢别人的文章列表'''
    user = User.query.get_or_404(id)
    page = request.args.get('page', 1, type=int)
    per_page = min(
        request.args.get(
            'per_page', current_app.config['POSTS_PER_PAGE'], type=int), 100)
    data = Post.to_collection_dict(
        user.liked_posts.order_by(Post.timestamp.desc()), page, per_page,
        'api.get_user_liked_posts', id=id)
    return jsonify(data)

效果图如下:

2 喜欢文章

4. 提交代码

$ git add .
$ git commit -m "13. 喜欢文章"
$ git checkout master
$ git merge dev
$ git branch -d dev

将本地 master 分支代码上传到 Github 代码仓库中的 master 分支:

$ git push -u origin master

打上标签 tag并上传:

$ git tag v0.13
$ git push origin v0.13

代码已上传到 https://github.com/wangy8961/flask-vuejs-madblog/tree/v0.13 ,欢迎star

分类: Vue.js
标签: API RESTful vuejs flask like
未经允许不得转载: LIFE & SHARE - 王颜公子 » Flask Vue.js全栈开发|第13章:喜欢文章

分享

作者

作者头像

Madman

如果博文内容有误或其它任何问题,欢迎留言评论,我会尽快回复; 或者通过QQ、微信等联系我

0 条评论

暂时还没有评论.

发表评论前请先登录