Flask Vue.js全栈开发|第11章:私信
Synopsis: 上一篇文章中用户收到的新评论通知有些问题,没考虑到评论被回复的情况,本文将修复这个 BUG。除了在用户发布的文章下面评论进行互动以外,用户之间还可以发送私密的信息,别人无法看到,类似于网络聊天。目前,用户之间可以随意发送私信,如果有人骚扰你,你也只能默默接收这些垃圾私信,下一篇将实现 黑名单 功能,可以屏蔽你讨厌的用户,对方无法 Follow 你,不会收到你新文章提醒,你也不会收到对方的骚扰信息
代码已上传到 https://github.com/wangy8961/flask-vuejs-madblog/tree/v0.11 ,欢迎star
1. 修复 BUG
修改 back-end/app/models.py
:
class User(PaginatedAPIMixin, db.Model): ... def new_recived_comments(self): '''用户收到的新评论计数 包括: 1. 用户的所有文章下面新增的评论 2. 用户发表的评论(或下面的子孙)被人回复了 ''' last_read_time = self.last_recived_comments_read_time or datetime(1900, 1, 1) # 用户发布的所有文章 user_posts_ids = [post.id for post in self.posts.all()] # 用户文章下面的新评论, 即评论的 post_id 在 user_posts_ids 集合中,且评论的 author 不是自己(文章的作者) q1 = set(Comment.query.filter(Comment.post_id.in_(user_posts_ids), Comment.author != self).all()) # 用户发表的评论被人回复了,找到每个用户评论的所有子孙 q2 = set() for c in self.comments: q2 = q2 | c.get_descendants() q2 = q2 - set(self.comments.all()) # 除去子孙中,用户自己发的(因为是多级评论,用户可能还会在子孙中盖楼),自己回复的不用通知 # 用户收到的总评论集合为 q1 与 q2 的并集 recived_comments = q1 | q2 # 最后,再过滤掉 last_read_time 之前的评论 return len([c for c in recived_comments if c.timestamp > last_read_time]) ...
同时,修改发表评论和删除评论的 API:
@bp.route('/comments/', methods=['POST']) @token_auth.login_required def create_comment(): '''在某篇博客文章下面发表新评论''' data = request.get_json() if not data: return bad_request('You must post JSON data.') if 'body' not in data or not data.get('body').strip(): return bad_request('Body is required.') if 'post_id' not in data or not data.get('post_id'): return bad_request('Post id is required.') post = Post.query.get_or_404(int(data.get('post_id'))) comment = Comment() comment.from_dict(data) comment.author = g.current_user comment.post = post # 必须先添加该评论,后续给各用户发送通知时,User.new_recived_comments() 才能是更新后的值 db.session.add(comment) db.session.commit() # 更新数据库,添加评论记录 # 添加评论时: # 1. 如果是一级评论,只需要给文章作者发送新评论通知 # 2. 如果不是一级评论,则需要给文章作者和该评论的所有祖先的作者发送新评论通知 users = set() users.add(comment.post.author) # 将文章作者添加进集合中 if comment.parent: ancestors_authors = {c.author for c in comment.get_ancestors()} users = users | ancestors_authors # 给各用户发送新评论通知 for u in users: u.add_notification('unread_recived_comments_count', u.new_recived_comments()) db.session.commit() # 更新数据库,写入新通知 response = jsonify(comment.to_dict()) response.status_code = 201 # HTTP协议要求201响应包含一个值为新资源URL的Location头部 response.headers['Location'] = url_for('api.get_comment', id=comment.id) return response @bp.route('/comments/<int:id>', methods=['DELETE']) @token_auth.login_required def delete_comment(id): '''删除单个评论''' comment = Comment.query.get_or_404(id) if g.current_user != comment.author and g.current_user != comment.post.author: return error_response(403) # 删除评论时: # 1. 如果是一级评论,只需要给文章作者发送新评论通知 # 2. 如果不是一级评论,则需要给文章作者和该评论的所有祖先的作者发送新评论通知 users = set() users.add(comment.post.author) # 将文章作者添加进集合中 if comment.parent: ancestors_authors = {c.author for c in comment.get_ancestors()} users = users | ancestors_authors # 必须先删除该评论,后续给各用户发送通知时,User.new_recived_comments() 才能是更新后的值 db.session.delete(comment) db.session.commit() # 更新数据库,删除评论记录 # 给各用户发送新评论通知 for u in users: u.add_notification('unread_recived_comments_count', u.new_recived_comments()) db.session.commit() # 更新数据库,写入新通知 return '', 204
2. 用户私信
2.1 数据模型
修改 back-end/app/models.py
,增加 Message
数据模型:
class User(PaginatedAPIMixin, db.Model): ... # 用户发送的私信 messages_sent = db.relationship('Message', foreign_keys='Message.sender_id', backref='sender', lazy='dynamic', cascade='all, delete-orphan') # 用户接收的私信 messages_received = db.relationship('Message', foreign_keys='Message.recipient_id', backref='recipient', lazy='dynamic', cascade='all, delete-orphan') # 用户最后一次查看私信的时间 last_messages_read_time = db.Column(db.DateTime) ... def new_recived_messages(self): '''用户未读的私信计数''' last_read_time = self.last_messages_read_time or datetime(1900, 1, 1) return Message.query.filter_by(recipient=self).filter( Message.timestamp > last_read_time).count() class Message(PaginatedAPIMixin, db.Model): __tablename__ = 'messages' id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) sender_id = db.Column(db.Integer, db.ForeignKey('users.id')) recipient_id = db.Column(db.Integer, db.ForeignKey('users.id')) def
未经允许不得转载: LIFE & SHARE - 王颜公子 » Flask Vue.js全栈开发|第11章:私信
0 条评论
评论者的用户名
评论时间暂时还没有评论.