#!/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()