Esempio n. 1
0
    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()
Esempio n. 2
0
    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()
Esempio n. 3
0
    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)
Esempio n. 4
0
    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)
Esempio n. 5
0
    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()
Esempio n. 6
0
    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)
Esempio n. 7
0
    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)
Esempio n. 8
0
    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()
Esempio n. 9
0
    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()
Esempio n. 10
0
    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)
Esempio n. 11
0
    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()