def post(self, request): """对回答、问答评论进行投票或者修改已有的投票""" user_id = request._request.uid which_model = Answer if request.data.get("type", "") == "answer" else QAComment which_object = which_model.objects.filter( pk=request.data.get("id", None)).first() # 被投票的对象,可以是回答或者问答评论 if not which_object: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) # TODO 能否给自己投票? value = request.data.get("value", "0") value = bool(int(value)) # value采用数字 try: which_object.vote.update_or_create(user_id=user_id, defaults={'value': value}) except: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) # TODO 触发消息通知 if which_model == Answer and value == True: notification_handler.delay(user_id, which_object.user_id, 'LAN', which_object.id) elif which_model == QAComment and value == True: notification_handler.delay(user_id, which_object.user_id, 'LQAC', which_object.id) return self.success()
def post(self, request): """邀请回答,不能邀请自己、已回答用户,不能重复邀请同一用户回答同一问题""" slug = request.data.get("invited_slug", None) invited = UserProfile.objects.filter(slug=slug).first() if not invited: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) data = { "question": request.data.get("id", None), "inviting": request._request.uid, "invited": invited.uid, } s = InviteCreateSerializer(data=data) s.is_valid() if s.errors: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) s.validated_data["status"] = 0 try: instance = s.create(s.validated_data) except Exception as e: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) # TODO 发送消息通知 question = Question.objects.filter(pk=data.get('question')).first() notification_handler.delay(instance.inviting, instance.invited, 'I', question.id) return self.success()
def post(self, request, kind, id): """发表评论""" me = request.me # TODO 检查用户权限,另外能否自我评论? model = MAPPINGS.get(kind) if model is None: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) instance = model.objects.filter(pk=id, is_deleted=False).first() if instance is None: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) # 某些模型有草稿与正式版之分,需要进一步检测 if hasattr(model, "is_draft") and instance.is_draft: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) data = { "content": request.data.get("content") or "", } checker = CommentChecker(data=data) checker.is_valid() if checker.errors: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) try: comment = instance.comments.create(author=me, **checker.validated_data) except: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) formatter = MeCommentSerializer(instance=comment, context={"me": me}) # 触发消息通知 if kind == 'question': notification_handler.delay(me.pk, instance.author_id, 'CQ', comment.pk) if kind == 'answer': notification_handler.delay(me.pk, instance.author_id, 'CAN', comment.pk) if kind == 'article': notification_handler.delay(me.pk, instance.author_id, 'CAR', comment.pk) if kind == 'idea': notification_handler.delay(me.pk, instance.author_id, 'CI', comment.pk) if kind == 'comment': notification_handler.delay(me.pk, instance.author_id, 'R', comment.pk) return self.success(formatter.data)
def post(self, request, question_id): """写回答,可以是草稿,正式回答会真实删除草稿""" me = request.me # TODO 检查用户权限 question = Question.objects.filter(pk=question_id, is_deleted=False).first() if question is None: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) # TODO 现在允许自问自答,并且有相关的单元测试,是否修改? if question.answer_set.filter(author=me, is_draft=False, is_deleted=False).exists(): return self.error(errorcode.MSG_ANSWERED, errorcode.ANSWERED) data = { "content": request.data.get("content") or "", "is_draft": request.data.get("is_draft"), "is_anonymous": request.data.get("is_anonymous") or False, # 回答默认不匿名 } checker = AnswerChecker(data=data) checker.is_valid() if checker.errors: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) try: with atomic(): answer = Answer.objects.create(author=me, question=question, **checker.validated_data) if answer.is_draft is False: # TODO 可以异步或定时进行 question.answer_set.filter(author=me, is_draft=True).delete() # TODO 把本人收到的此问题的尚未回答的回答邀请全部设为已回答 except: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) formatter = MeAnswerSerializer(instance=answer, context={"me": me}) try: print('触发消息通知') notification_handler.delay(me.pk, question.author.pk, 'A', answer.pk) # TODO 是否也要给关注该问题的人发送通知,是否要异步发送 question_follows = QuestionFollow.objects.filter(question=question) for follow in question_follows: notification_handler.delay(me.pk, follow.user_id, 'AF', answer.pk) except Question.DoesNotExist as e: return self.error(e.args, errorcode.INVALID_DATA) return self.success(formatter.data)
def post(self, request, user_slug): '''''' uid = request._request.uid print(uid, '用户ID') idol_user = UserProfile.objects.filter(slug=user_slug).first() if not idol_user: return self.error('error', 404) if idol_user.uid == uid: return self.error('不能关注自己', 400) if FollowedUser.objects.filter(fans_id=uid, idol=idol_user).exists(): return self.error('不能重复关注', 400) fans = UserProfile.objects.get(uid=uid) FollowedUser.objects.create(fans=fans, idol=idol_user) # TODO 触发消息通知 notification_handler.delay(uid, idol_user.uid, 'O', idol_user.uid) return self.success()
def post(self, request): """对问题或回答发表评论""" user_id = request._request.uid which_model = Question if request.data.get( "type", "") == "question" else Answer # TODO 对评论发表评论 instance_pk = request.data.get("id", None) which_object = which_model.objects.filter(pk=instance_pk).first() if not which_object: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) data = { "user_id": user_id, # 评论者ID "content": request.data.get("content", None), # 评论内容 "reply_to_user": which_object.user_id, # 被评论者ID "content_object": which_object, } s = QACommentCreateSerializer(data=data) s.is_valid() if s.errors: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) data = { "user_id": s.validated_data["user_id"], "content": s.validated_data["content"], "reply_to_user": s.validated_data["reply_to_user"], } try: comment = which_object.comment.create(**data) except Exception as e: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) s = QACommentCreateSerializer(instance=comment) # TODO 触发消息通知 if request.data.get("type", "") == "question": # 评论问题 notification_handler.delay(user_id, which_object.user_id, 'CQ', comment.id) else: # 评论回答 notification_handler.delay(user_id, which_object.user_id, 'CAN', comment.id) return self.success(s.data)
def post(self, request, question_id): """回答问题""" user_id = request._request.uid data = { "question": question_id, "content": request.data.get("content", None), "user_id": user_id, } s = AnswerCreateSerializer(data=data) s.is_valid() if s.errors: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) try: with transaction.atomic(): instance = s.create(s.validated_data) # 保存回答后,把该用户收到的该问题的未回答邀请都设置为已回答 QuestionInvite.objects.filter(question=question_id, invited=user_id, status=0).update(status=2) except: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) s = AnswerCreateSerializer(instance=instance) # TODO 触发消息通知 try: print('触发消息通知') question = Question.objects.get(pk=question_id) notification_handler.delay(user_id, question.user_id, 'A', instance.id) # TODO 是否也要给关注该问题的人发送通知,是否要异步发送 question_follows = QuestionFollow.objects.filter(question=question) for follow in question_follows: notification_handler.delay(user_id, follow.user_id, 'AF', instance.id) except Question.DoesNotExist as e: return self.error(e.args, errorcode.INVALID_DATA) return self.success(s.data)
def post(self, request, question_id): """邀请回答,不能邀请自己、已经邀请过的用户、已经回答过的用户、主动拒绝的用户""" me = request.me question = Question.objects.filter(pk=question_id, is_deleted=False).first() if question is None: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) slug = request.data.get("slug") or "" # 不能邀请自己 if me.slug == slug: return self.error(errorcode.MSG_BAD_INVITE, errorcode.BAD_INVITE) he = self.get_user_by_slug(slug) if he is None: return self.error(errorcode.MSG_INVALID_SLUG, errorcode.INVALID_SLUG) # 不能重复邀请同一用户回答同一问题 if QuestionInvite.objects.filter(inviting=me, invited=he, question=question, is_deleted=False).exists(): return self.error(errorcode.MSG_BAD_INVITE, errorcode.BAD_INVITE) # 不能邀请已回答用户 if Answer.objects.filter(question=question, author=he, is_deleted=False).exists(): return self.error(errorcode.MSG_BAD_INVITE, errorcode.BAD_INVITE) # TODO 自动拒绝邀请 # TODO 如果不允许自问自答,则也不能邀请提问者 try: instance = QuestionInvite.objects.create(inviting=me, invited=he, question=question) except: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) # TODO 发送消息通知 notification_handler.delay(instance.inviting, instance.invited, 'I', question.pk) return self.success()
def post(self, request): """文章及其评论的投票""" user_id = request._request.uid which_model = Article if request.data.get("type", "") == "article" else ArticleComment which_object = which_model.objects.filter(pk=request.data.get("id", None)).first() if not which_object: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) # TODO 能否给自己投票 value = request.data.get("value", "0") value = bool(int(value)) # value采用数字 try: which_object.vote.update_or_create(user_id=user_id, defaults={"value": value}) except: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) # TODO 触发消息通知 if which_model == Article and value == True: # 给文章点赞 notification_handler.delay(user_id, which_object.user_id, 'LAR', which_object.id) elif which_model == ArticleComment and value == True: # 给文章评论点赞 notification_handler.delay(user_id, which_object.user_id, 'LAC', which_object.id) return self.success()
def post(self, request): """评论文章,必须是已发表的文章""" data = { "article": request.data.get("id", None), "user_id": request._request.uid, "content": request.data.get("content", None), } s = ArticleCommentSerializer(data=data) s.is_valid() if s.errors: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) article = s.validated_data["article"] s.validated_data["reply_to_user"] = article.user_id try: comment = s.create(s.validated_data) except Exception as e: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) s = ArticleCommentSerializer(instance=comment, context={"me": UserProfile.objects.get(pk=request._request.uid)}) # TODO 触发消息通知 # 某人评论了你的文章 notification_handler.delay(request._request.uid, article.user_id, 'CAR', comment.id) return self.success(s.data)
def post(self, request, kind, id): """投票,如果已经投过票则直接修改,每人对每个对象只能投一票""" me = request.me # TODO 检查用户权限 model = MAPPINGS.get(kind) if model is None: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) instance = model.objects.filter(pk=id, is_deleted=False).first() if instance is None: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) if hasattr(model, "is_draft") and instance.is_draft: return self.error(errorcode.MSG_NO_DATA, errorcode.NO_DATA) # TODO 能给自己投票吗? if model == Idea: # 想法只接受赞成票 data = {"value": True} else: data = { "value": request.data.get("value"), } checker = VoteChecker(data=data) checker.is_valid() if checker.errors: return self.error(errorcode.MSG_INVALID_DATA, errorcode.INVALID_DATA) try: instance.votes.update_or_create(author=me, defaults=checker.validated_data) except: return self.error(errorcode.MSG_DB_ERROR, errorcode.DB_ERROR) # 触发消息通知 if kind == 'comment': content_object = instance.content_object if isinstance(content_object, Article): notification_handler.delay(me.pk, instance.author_id, 'LAC', instance.pk) if isinstance(content_object, Answer): notification_handler.delay(me.pk, instance.author_id, 'LQAC', instance.pk) if isinstance(content_object, Idea): notification_handler.delay(me.pk, instance.author_id, 'LIC', instance.pk) if kind == 'answer': notification_handler.delay(me.pk, instance.author_id, 'LAN', instance.pk) if kind == 'article': notification_handler.delay(me.pk, instance.author_id, 'LAR', instance.pk) if kind == 'idea': notification_handler.delay(me.pk, instance.author_id, 'LI', instance.pk) return self.success()