09 | 帖子相关功能开发
表结构设计
apps/community/models.py
class Post(BaseModel): user = ForeignKeyField(User, verbose_name="用户") title = CharField(max_length=200, verbose_name="标题", null=True) group = ForeignKeyField(CommunityGroup, verbose_name="小组") comment_nums = IntegerField(default=0, verbose_name="评论数") is_excellent = BooleanField(default=0, verbose_name="是否精华") is_hot = BooleanField(default=0, verbose_name="是否热门") content = TextField(verbose_name="内容") @classmethod def extend(cls): return cls.select(cls, User.id, User.nick_name).join(User) class PostComment(BaseModel): # 评论和回复 user = ForeignKeyField(User, verbose_name="用户", related_name="author") post = ForeignKeyField(Post, verbose_name="帖子") parent_comment = ForeignKeyField('self', null=True, verbose_name="评论", related_name="comments_parent") reply_user = ForeignKeyField(User, verbose_name="用户", related_name="replyed_author", null=True) content = CharField(max_length=1000, verbose_name="内容") reply_nums = IntegerField(default=0, verbose_name="回复数") like_nums = IntegerField(default=0, verbose_name="点赞数") @classmethod def extend(cls): #1. 多表join #2. 多字段映射同一个model author = User.alias() relyed_user = User.alias() return cls.select(cls, Post, relyed_user.id, relyed_user.nick_name, author.id, author.nick_name).join( Post, join_type=JOIN.LEFT_OUTER, on=cls.post).switch(cls).join(author, join_type=JOIN.LEFT_OUTER, on=cls.user).switch(cls).join( relyed_user, join_type=JOIN.LEFT_OUTER, on=cls.reply_user ) class CommentLike(BaseModel): # 评论点赞 user = ForeignKeyField(User, verbose_name="用户") post_comment = ForeignKeyField(PostComment, verbose_name="帖子")
发布新帖
apps/community/forms.py 参数校验
class PostForm(Form): title = StringField("标题", validators=[DataRequired("请输入标题")]) content = StringField("内容", validators=[DataRequired("请输入内容")])
apps/community/handler.py 发布帖子hander
class PostHandler(RedisHandler): @authenticated_async async def get(self,group_id, *args, **kwargs): #获取小组内的帖子 pass @authenticated_async async def post(self,group_id, *args, **kwargs): #小组内发帖 re_data = {} try: group = await self.application.objects.get(CommunityGroup, id=int(group_id)) group_member = await self.application.objects.get(CommunityGroupMember, user=self.current_user, community=group, status="agree") param = self.request.body.decode("utf8") param = json.loads(param) form = PostForm.from_json(param) if form.validate(): post = await self.application.objects.create(Post, user=self.current_user,title=form.title.data, content=form.content.data, group=group) re_data["id"] = post.id else: self.set_status(400) for field in form.errors: re_data[field] = form.errors[field][0] except CommunityGroup.DoesNotExist as e: self.set_status(404) except CommunityGroupMember.DoesNotExist as e: self.set_status(403) self.finish(re_data)
apps/community/urls.py路由
urlpattern = ( url("/posts/([0-9]+)/", PostDetailHandler), )
联调
获取帖子
apps/community/handler.py 获取帖子hander 重写get方法
class PostHandler(RedisHandler): @authenticated_async async def get(self,group_id, *args, **kwargs): #获取小组内的帖子 post_list = [] try: group = await self.application.objects.get(CommunityGroup, id=int(group_id)) group_member = await self.application.objects.get(CommunityGroupMember, user=self.current_user, community=group, status="agree") posts_query = Post.extend() c = self.get_argument("c", None) if c == "hot": posts_query = posts_query.filter(Post.is_hot == True) if c == "excellent": posts_query = posts_query.filter(Post.is_excellent == True) posts = await self.application.objects.execute(posts_query) for post in posts: item_dict = { "user":{ "id":post.user.id, "nick_name": post.user.nick_name }, "id":post.id, "title":post.title, "content":post.content, "comment_nums":post.comment_nums } post_list.append(item_dict) except CommunityGroupMember.DoesNotExist as e: self.set_status(403) except CommunityGroup.DoesNotExist as e: self.set_status(404) self.finish(json.dumps(post_list)) @authenticated_async async def post(self,group_id, *args, **kwargs): #小组内发帖 re_data = {} try: group = await self.application.objects.get(CommunityGroup, id=int(group_id)) group_member = await self.application.objects.get(CommunityGroupMember, user=self.current_user, community=group, status="agree") param = self.request.body.decode("utf8") param = json.loads(param) form = PostForm.from_json(param) if form.validate(): post = await self.application.objects.create(Post, user=self.current_user,title=form.title.data, content=form.content.data, group=group) re_data["id"] = post.id else: self.set_status(400) for field in form.errors: re_data[field] = form.errors[field][0] except CommunityGroup.DoesNotExist as e: self.set_status(404) except CommunityGroupMember.DoesNotExist as e: self.set_status(403) self.finish(re_data)
联调
帖子详情
apps/community/handler.py 帖子详情
# 获取帖子详情 class PostDetailHandler(RedisHandler): @authenticated_async async def get(self, post_id, *args, **kwargs): #获取某一个帖子的详情 re_data = {} post_details = await self.application.objects.execute(Post.extend().where(Post.id==int(post_id))) re_count = 0 for data in post_details: item_dict = {} item_dict["user"] = model_to_dict(data.user) item_dict["title"] = data.title item_dict["content"] = data.content item_dict["comment_nums"] = data.comment_nums item_dict["add_time"] = data.add_time.strftime("%Y-%m-%d") re_data = item_dict re_count += 1 if re_count == 0: self.set_status(404) self.finish(re_data)
apps/community/urls.py路由
urlpattern = ( url("/posts/([0-9]+)/", PostDetailHandler), )
联调
帖子评论相关功能开发
添加评论
apps/community/forms.py 参数校验
class PostComentForm(Form): content = StringField("内容", validators=[DataRequired("请输入评论内容"), Length(min=3, message="内容不能少于3个字符")])
apps/community/handler.py 帖子评论handler
# 帖子评论 class PostCommentHanlder(RedisHandler): @authenticated_async async def get(self, post_id, *args, **kwargs): #获取帖子的所有评论 pass @authenticated_async async def post(self, post_id, *args, **kwargs): #新增评论 re_data = {} param = self.request.body.decode("utf8") param = json.loads(param) form = PostComentForm.from_json(param) if form.validate(): try: post = await self.application.objects.get(Post, id=int(post_id)) post_comment = await self.application.objects.create(PostComment, user=self.current_user, post=post, content=form.content.data) post.comment_nums += 1 await self.application.objects.update(post) re_data["id"] = post_comment.id re_data["user"] = {} re_data["user"]["nick_name"] = self.current_user.nick_name re_data["user"]["id"] = self.current_user.id except Post.DoesNotExist as e: self.set_status(404) else: self.set_status(400) for field in form.errors: re_data[field] = form.errors[field][0] self.finish(re_data)
apps/community/urls.py路由
urlpattern = ( url("/posts/([0-9]+)/comments/", PostCommentHanlder), )
获取帖子评论列变
apps/community/handler.py 帖子评论列表handler 重写get方法
class PostCommentHanlder(RedisHandler): @authenticated_async async def get(self, post_id, *args, **kwargs): #获取帖子的所有评论 re_data = [] try: post = await self.application.objects.get(Post, id=int(post_id)) post_coments = await self.application.objects.execute( PostComment.extend().where(PostComment.post==post, PostComment.parent_comment.is_null(True)).order_by(PostComment.add_time.desc()) ) for item in post_coments: has_liked = False try: comments_like = await self.application.objects.get(CommentLike, post_comment_id=item.id, user_id=self.current_user.id) has_liked = True except CommentLike.DoesNotExist: pass item_dict = { "user":model_to_dict(item.user), "content":item.content, "reply_nums":item.reply_nums, "like_nums": item.like_nums, "has_liked": has_liked, "id": item.id, } re_data.append(item_dict) except Post.DoesNotExist as e: self.set_status(404) self.finish(self.finish(json.dumps(re_data, default=json_serial))) @authenticated_async async def post(self, post_id, *args, **kwargs): #新增评论 re_data = {} param = self.request.body.decode("utf8") param = json.loads(param) form = PostComentForm.from_json(param) if form.validate(): try: post = await self.application.objects.get(Post, id=int(post_id)) post_comment = await self.application.objects.create(PostComment, user=self.current_user, post=post, content=form.content.data) post.comment_nums += 1 await self.application.objects.update(post) re_data["id"] = post_comment.id re_data["user"] = {} re_data["user"]["nick_name"] = self.current_user.nick_name re_data["user"]["id"] = self.current_user.id except Post.DoesNotExist as e: self.set_status(404) else: self.set_status(400) for field in form.errors: re_data[field] = form.errors[field][0] self.finish(re_data)
联调
帖子回复
添加回复功能
apps/community/forms.py 参数校验
class CommentReplyForm(Form): replyed_user = IntegerField("回复用户", validators=[DataRequired("请输入回复用户")]) content = StringField("内容", validators=[DataRequired("请输入评论内容"), Length(min=3, message="内容不能少于3个字符")])
apps/community/handler.py 帖子回复handler
# 帖子回复 class CommentReplyHandler(RedisHandler): @authenticated_async async def get(self, comment_id, *args, **kwargs): pass @authenticated_async async def post(self, comment_id, *args, **kwargs): # 添加回复 re_data = {} param = self.request.body.decode("utf8") param = json.loads(param) form = CommentReplyForm.from_json(param) if form.validate(): try: comment = await self.application.objects.get(PostComment, id=int(comment_id)) reply_user = await self.application.objects.get(User, id=form.replyed_user.data) post = await self.application.objects.get(Post, id=int(comment.post_id)) reply = await self.application.objects.create(PostComment, post=post, user=self.current_user, parent_comment=comment, reply_user=reply_user, content=form.content.data) # 修改comment的回复数 comment.reply_nums += 1 await self.application.objects.update(comment) re_data["id"] = reply.id re_data["user"] = { "id": self.current_user.id, "nick_name": self.current_user.nick_name } # 写入消息 await self.application.objects.create(Message, sender=self.current_user, receiver=reply_user, message_type=2, parent_content=comment.content, message=form.content.data) except PostComment.DoesNotExist as e: self.set_status(404) except User.DoesNotExist as e: self.set_status(400) re_data["replyed_user"] = "用户不存在" else: self.set_status(400) for field in form.errors: re_data[field] = form.errors[field][0] self.finish(re_data)
apps/community/urls.py路由
urlpattern = ( url("/comments/([0-9]+)/likes/", CommentsLikeHanlder), )
获取回复列表
apps/community/handler.py 获取帖子回复列表 handler 重写get方法
# 帖子回复 class CommentReplyHandler(RedisHandler): @authenticated_async async def get(self, comment_id, *args, **kwargs): re_data = [] comment_replys = await self.application.objects.execute(PostComment.extend().where(PostComment.parent_comment_id==int(comment_id))) for item in comment_replys: item_dict = { "user":model_to_dict(item.user), "content":item.content, "reply_nums":item.reply_nums, "add_time":item.add_time.strftime("%Y-%m-%d"), "id":item.id } re_data.append(item_dict) self.finish(self.finish(json.dumps(re_data, default=json_serial))) @authenticated_async async def post(self, comment_id, *args, **kwargs): # 添加回复 re_data = {} param = self.request.body.decode("utf8") param = json.loads(param) form = CommentReplyForm.from_json(param) if form.validate(): try: comment = await self.application.objects.get(PostComment, id=int(comment_id)) reply_user = await self.application.objects.get(User, id=form.replyed_user.data) post = await self.application.objects.get(Post, id=int(comment.post_id)) reply = await self.application.objects.create(PostComment, post=post, user=self.current_user, parent_comment=comment, reply_user=reply_user, content=form.content.data) # 修改comment的回复数 comment.reply_nums += 1 await self.application.objects.update(comment) re_data["id"] = reply.id re_data["user"] = { "id": self.current_user.id, "nick_name": self.current_user.nick_name } # 写入消息 await self.application.objects.create(Message, sender=self.current_user, receiver=reply_user, message_type=2, parent_content=comment.content, message=form.content.data) except PostComment.DoesNotExist as e: self.set_status(404) except User.DoesNotExist as e: self.set_status(400) re_data["replyed_user"] = "用户不存在" else: self.set_status(400) for field in form.errors: re_data[field] = form.errors[field][0] self.finish(re_data)
在这里使用了连接多个表进行查询和对字段起别名
@classmethod def extend(cls): #1. 多表join #2. 多字段映射同一个model author = User.alias() relyed_user = User.alias() return cls.select(cls, Post, relyed_user.id, relyed_user.nick_name, author.id, author.nick_name).join( Post, join_type=JOIN.LEFT_OUTER, on=cls.post).switch(cls).join(author, join_type=JOIN.LEFT_OUTER, on=cls.user).switch(cls).join( relyed_user, join_type=JOIN.LEFT_OUTER, on=cls.reply_user )
联调
评论点赞
apps/community/handler.py 评论点赞handler
# 帖子点赞 class CommentsLikeHanlder(RedisHandler): @authenticated_async async def post(self, comment_id, *args, **kwargs): re_data = {} try: comment = await self.application.objects.get(PostComment, id=int(comment_id)) comment_like = await self.application.objects.create(CommentLike, user=self.current_user, post_comment=comment) comment.like_nums += 1 await self.application.objects.update(comment) re_data["id"] = comment_like.id except PostComment.DoesNotExist as e: self.set_status(404) self.finish(re_data)
apps/community/urls.py路由
urlpattern = ( # 小组功能开发 url("/comments/([0-9]+)/likes/", CommentsLikeHanlder), )
联调