qa_blend_manager.py 11.6 KB
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 问答对外暴露的方法
from __future__ import unicode_literals, absolute_import, print_function

from django.db.models import Q, Count, Sum
from gm_types.mimas import (
    VIDEO_SOURCE_TYPE,
)

from communal.normal_manager import (
    user_manager,
)
from qa.utils import const_strings  # view_record model type
from utils.base_manager import (
    BaseManager,
)
from .answer_manager import AnswerManager
from .question_manager import QuestionManager
from .answer_reply_manager import AnswerReplyManager
from .qa_social_manager import QaSocialService

from .qa_media_manager import (
    answer_media,
    question_media,
)


class QaBlendManager(BaseManager):
    """
    问答数据混合相关
    """
    def __init__(self):
        self.answer_manager = AnswerManager()
        self.question_manager = QuestionManager()
        self.answer_replies = AnswerReplyManager()
        self.qa_social_manager = QaSocialService()
        self.answer_media = answer_media
        self.question_media = question_media

    # 用户信息
    @staticmethod
    def get_users_info(user_ids, viewer_user_id=None):

        user_dic = user_manager.convert_user_info(
            viewer_user_id=viewer_user_id,
            author_ids=user_ids
        )
        return user_dic

    def get_question_all_answer_vote_nums(self, question_ids):
        """
        获取问题下所有回答的点赞数总和
        :param question_ids:
        :return:
        """
        _nums_dic = {}
        favor_nums = self.answer_manager.model.objects.filter(
            question_id__in=question_ids, is_online=True
        ).values_list("question_id").annotate(snt=Sum("like_num"))

        for question_id, snt in favor_nums:
            _nums_dic[question_id] = snt

        return _nums_dic

    def get_user_publish_answer_nums(self, user_ids):
        """
        获取用户发布的总回答数
        :param user_ids:
        :return:
        """
        _nums_dic = {}
        answer_nums = self.answer_manager.model.objects.filter(
            user__in=user_ids, is_online=True
        ).values_list("user").annotate(cnt=Count("id"))

        for user_id, cnt in answer_nums:
            _nums_dic[user_id] = cnt

        return _nums_dic

    def get_user_publish_answer_vote_nums(self, user_ids):
        """
        获取用户发布的所有回答的点赞数
        :param user_ids:
        :return:
        """
        _nums_dic = {}
        favor_nums = self.answer_manager.model.objects.filter(
            user__in=user_ids, is_online=True
        ).values_list("user").annotate(snt=Sum("like_num"))

        for user_id, snt in favor_nums:
            _nums_dic[user_id] = snt

        return _nums_dic

    def get_answer_objs(self, query, order_by):
        """
        通过query获取回答对象
        :param query:
        :param order_by:
        :return:
        """
        if not query:
            query = Q()

        if not order_by:
            order_by = []

        return self.get_objs_by_query_and_order(
            model=self.answer_manager.model,
            query=query,
            order_by=order_by
        )

    def get_question_objs(self, query, order_by):
        """
        通过query获取问题对象
        :param query:
        :param order_by:
        :return:
        """
        if not query:
            query = Q()

        if not order_by:
            order_by = []

        return self.get_objs_by_query_and_order(
            model=self.question_manager.model,
            query=query,
            order_by=order_by
        )

    def get_questions_base_data(self, question_objs, viewer_user_id=None, need_social_info=False):
        """
        获取问题的基本信息
        :param question_objs:
        :param viewer_user_id:
        :param need_social_info:
        :return:
        """
        questions_result = {}

        if not question_objs:
            return questions_result

        questions_result = self.question_manager.get_question_base_list_info_by_obj_list(question_objs)
        questions = questions_result.get("questions", {})
        _valid_ids = list(questions.keys())

        if need_social_info:
            ans_dic = self.qa_social_manager.get_answer_num_by_question_ids(_valid_ids)
            qvn_dic = self.qa_social_manager.get_amounts_from_redis(
                qa_ids=_valid_ids,
                const_string=const_strings.QUESTION_VIEW
            )
            question_favored_dic = self.qa_social_manager.get_question_is_favored_by_question_ids(
                _valid_ids,
                viewer_user_id=viewer_user_id
            )
        else:
            ans_dic = {}  # 回答数
            qvn_dic = {}  # 浏览量
            question_favored_dic = {}  # 收藏状态

        # 问题数据组装
        for question_id, question in questions.items():
            question.update({
                "answer_num": ans_dic.get(question_id, 0),
                "view_num": qvn_dic.get(question_id, 0),
                "is_favored": question_favored_dic.get(question_id, False),
            })

        return questions_result

    def get_answers_base_data(self, answer_objs, viewer_user_id=None, need_social_info=False):
        """
        获取回答的基本信息
        :param answer_objs:
        :param viewer_user_id:
        :param need_social_info:
        :return:
        """
        _data = {}
        if not answer_objs:
            return _data

        answer_results = self.answer_manager.get_answer_base_list_info_by_obj_list(answer_objs)
        answers = answer_results.get("answers", {})

        _valid_ids = list(answers.keys())

        # 社交信息
        if need_social_info:
            answer_voted_dic = self.qa_social_manager.get_answer_is_voted_by_answer_ids(
                _valid_ids, viewer_user_id=viewer_user_id)
            reply_nums_dic = self.qa_social_manager.get_answer_reply_nums_by_answer_ids(_valid_ids)
            avn_dic = self.qa_social_manager.get_amounts_from_redis(
                _valid_ids,
                const_string=const_strings.ANSWER_VIEW
            )
            answer_favored_dic = self.qa_social_manager.get_answer_is_favored_by_answer_ids(
                _valid_ids,
                viewer_user_id=viewer_user_id
            )
        else:
            answer_voted_dic = {}  # 点赞状态
            reply_nums_dic = {}  # 一级评论与子评论
            avn_dic = {}  # 浏览量
            answer_favored_dic = {}  # 关注状态

        for answer_id, base_data in answers.items():
            base_data.update({
                "is_voted": answer_voted_dic.get(answer_id, False),
                "is_favored": answer_favored_dic.get(answer_id, False),
                "view_num": avn_dic.get(answer_id, 0),
            })
            _reply_num_dic = reply_nums_dic.get(answer_id, {})
            base_data.update(_reply_num_dic)

        return answer_results

    # 以下信息基本是卡片数据整合
    def get_questions_info_by_objs(self, question_objs, viewer_user_id=None, need_social_info=False, need_user_info=False):
        """
        通过问题对象获取数据
        :param question_objs:
        :param viewer_user_id:
        :param need_social_info:
        :param need_user_info:
        :return:
        """
        _data = {}

        if not question_objs:
            return _data

        questions_result = self.get_questions_base_data(
            question_objs,
            viewer_user_id=viewer_user_id,
            need_social_info=need_social_info
        )
        questions = questions_result.get("questions", {})
        valid_question_ids = list(questions.keys())
        q_text_dic = questions_result.get("raw_medias", {})

        # 用户数据
        if need_user_info:
            _user_infos_dic = self.get_users_info(
                questions_result.get("valid_user_ids", []),
                viewer_user_id=viewer_user_id
            )
        else:
            _user_infos_dic = {}

        # 标签
        tags_info_dic = self.question_manager.get_tags_info_by_question_ids(valid_question_ids)
        # 图片
        question_images_dic = self.question_media.get_qa_images(q_text_dic)
        # 视频
        question_videos_dic = self.question_media.get_qa_videos(q_text_dic, source_type=VIDEO_SOURCE_TYPE.QUESTION)

        # 问题数据组装
        for question_id, question in questions.items():
            _user_id = question.get("user_id", 0)
            question.update({
                "user_info": _user_infos_dic.get(_user_id, {}),
                "images": question_images_dic.get(question_id, []),
                "video_list": question_videos_dic.get(question_id, []),
                "tags": tags_info_dic.get(question_id, []),
            })

        return questions

    # 以下信息基本是卡片数据整合
    def get_answer_info_by_objs(self, answer_objs, viewer_user_id=None, need_social_info=False, image_url_sources=None):
        """
        通过回答对象获取数据
        :param answer_objs:
        :param viewer_user_id:
        :param need_social_info:
        :param image_url_sources:
        :return:
        """
        answers_dic = {}
        if not answer_objs:
            return answers_dic

        answers_result = self.get_answers_base_data(
            answer_objs,
            viewer_user_id=viewer_user_id,
            need_social_info=need_social_info
        )
        answers_dic = answers_result.get("answers", {})
        a_text_dic = answers_result.get("raw_medias", {})

        # 用户信息
        _user_infos_dic = self.get_users_info(
            answers_result.get("valid_user_ids", []),
            viewer_user_id=viewer_user_id
        )

        answer_images_dic = self.answer_media.get_qa_images(a_text_dic, image_url_sources=image_url_sources)
        # 视频
        answer_videos_dic = self.answer_media.get_qa_videos(a_text_dic, source_type=VIDEO_SOURCE_TYPE.ANSWER)

        for answer_id, answer in answers_dic.items():
            _user_id = answer.get("user_id", 0)
            answer.update({
                "user_info": _user_infos_dic.get(_user_id, {}),
                "images": answer_images_dic.get(answer_id, []),
                "video_list": answer_videos_dic.get(answer_id, [])
            })

        return answers_dic

    def get_question_info_by_ids(self, question_ids, viewer_user_id=None, need_social_info=False, need_user_info=False):
        """
        获取问题相关信息  这里使用的是问题的默认query
        :param question_ids:
        :param viewer_user_id:
        :param need_social_info: 是否需要社交信息
        :param need_user_info: 是否需要用户信息
        :return:
        """
        _question_objs = self.question_manager.get_objs_by_ids(question_ids)
        return self.get_questions_info_by_objs(
            _question_objs,
            viewer_user_id=viewer_user_id,
            need_social_info=need_social_info,
            need_user_info=need_user_info
        )

    def get_answer_info_by_ids(self, answer_ids, image_url_sources=None, viewer_user_id=None, need_social_info=False):
        """
        获取回答相关信息  # 这里使用的是回答的默认query
        :param answer_ids:
        :param image_url_sources:
        :param viewer_user_id:
        :param need_social_info:  是否需要社交信息
        :return:
        """
        _answer_objs = self.answer_manager.get_objs_by_ids(answer_ids)
        return self.get_answer_info_by_objs(
            _answer_objs,
            viewer_user_id=viewer_user_id,
            need_social_info=need_social_info,
            image_url_sources=image_url_sources
        )


qa_manager = QaBlendManager()