#!/usr/bin/env python # -*- coding: utf-8 -*- # 问答卡片性能优化接口 from operator import itemgetter from django.db.models import Q from gm_rpcd.all import bind from gm_types.error import ERROR from gm_types.mimas import ( MEDIA_IMAGE_URL_SOURCE, GRABBING_PLATFORM, ) from qa.manager.qa_blend_manager import ( qa_manager, ) from qa.utils.decorator import listing from qa.tasks import ( add_answer_view, ) from talos.services import UserConvertService from utils.rpc import ( gen, rpc_client, get_current_user, logging_exception, ) from utils.group_routine import GroupRoutine @bind('qa/question_answer/list_by_ids_v2') @listing() def get_qa_list_by_ids_v2(answer_ids, viewer_user_id=None): """ 通过回答id,获取卡片数据 :param answer_ids: :param viewer_user_id: :return: """ if not answer_ids: return [] # 回答信息 answer_ids = list(map(int, answer_ids)) answer_objs = qa_manager.get_answer_objs( query=Q(pk__in=answer_ids, is_online=True, question__is_online=True), order_by=[] ) answers_dic = qa_manager.get_answer_info_by_objs( answer_objs, viewer_user_id=viewer_user_id, need_social_info=True ) # sql查询 # 问题信息 question_ids = set(map(itemgetter("question_id"), answers_dic.values())) question_objs = qa_manager.get_question_objs( query=Q(pk__in=question_ids, is_online=True), order_by=[] ) questions_dic = qa_manager.get_questions_info_by_objs(question_objs) # sql查询 answer_list = [] valid_answer_ids = [] for answer_id in answer_ids: _answer_data = answers_dic.get(answer_id, {}) if _answer_data: _question_id = _answer_data.get("question_id", 0) _user_info = _answer_data.get("user_info", {}) _answer_data.update({ "question": questions_dic.get(_question_id, {}), "is_following": _user_info.get("is_following", False), }) answer_list.append(_answer_data) valid_answer_ids.append(answer_id) add_answer_view.delay(answer_ids=valid_answer_ids) return answer_list @bind("qa/question/new_answer_list/v2") def get_new_answer_list_v2(answer_ids, viewer_user_id=None, return_sorted=False): """ 问题详情页回答列表,回答id来自策略推荐 :param answer_ids: :param viewer_user_id: 当前浏览用户id :param return_sorted: 是否需要按照ids 排序 :return: """ result = {} if not answer_ids: return result answer_ids = qa_manager.filter_ids(answer_ids) answer_objs = qa_manager.get_answer_objs( query=Q(pk__in=answer_ids, is_online=True, question__is_online=True), order_by=[] ) # header头图 answer_header_images = qa_manager.answer_media.get_qa_header_images(qa_ids=answer_ids) # 其他信息 user_ids = [answer.user_id for answer in answer_objs] pub_answer_nums_dic = qa_manager.get_user_publish_answer_nums(user_ids) vote_nums_dic = qa_manager.get_user_publish_answer_vote_nums(user_ids) # 回答信息 answers_data = qa_manager.get_answer_info_by_objs( answer_objs, viewer_user_id=viewer_user_id, need_social_info=True, image_url_sources=[MEDIA_IMAGE_URL_SOURCE.CREATE] ) for answer_id, answer_data in answers_data.items(): _user_id = answer_data.get("user_id", 0) answer_data.update({ "header_images": answer_header_images.get(answer_id, []), "answer_user_pub_nums": pub_answer_nums_dic.get(_user_id, 0), "answer_user_pub_favor_nums": vote_nums_dic.get(_user_id, 0), }) result[str(answer_id)] = answer_data if return_sorted: result = sorted(result, key=lambda item: answer_ids.index(item.get('id'))) return result @bind("qa/answer_reply/include_sub_comments_for_answer_list") def get_answer_reply_list_include_sub_comments(answer_ids, viewer_user_id=None, start_num=0, count=2): """ 获取问题详情页回答列表评论 :param answer_ids: :param viewer_user_id:当前浏览用户id :param start_num: :param count: :return: {} """ result = {} if not answer_ids: return result _reply_list, _map_dic = [], {} for answer_id in answer_ids: replies = list(qa_manager.get_objs_by_query_and_order( model=qa_manager.answer_replies.model, query=Q(answer_id=answer_id, is_online=True, first_reply__isnull=True), order_by=["id"] ).only("id", "user", "content", "create_time", "like_num")[start_num: start_num + count]) _reply_list.extend(replies) _map_dic[answer_id] = [reply.id for reply in replies] replies_data = qa_manager.answer_replies.get_reply_data_by_replies_obj( replies=_reply_list, viewer_user_id=viewer_user_id, need_sub_comments=True ) for answer_id, reply_ids in _map_dic.items(): result[str(answer_id)] = [replies_data.get(reply_id, {}) for reply_id in reply_ids] return result @bind("qa/question/get_question_rel_infos") def get_question_rel_infos(question_id=None, answer_id=None): """ 获取问题关联的信息 :param question_id: 问题id :return: """ result = {} if not question_id and not answer_id: return result if answer_id: answer_obj = qa_manager.get_answer_objs( Q(pk=answer_id, is_online=True), None).only("question_id").first() if not answer_obj: return gen(ERROR.ANSWER_NOT_FOUND) question_id = answer_obj.question_id question_obj = qa_manager.get_question_objs(Q(pk=question_id), None).only("id", "user").first() if not question_obj: return gen(ERROR.QUESTION_NOT_FOUND) user = get_current_user() user_id = user and user.id if not question_obj.user_can_view(user_id): return gen(ERROR.QUESTION_NOT_FOUND) _question_id = question_obj.id v1_tags_info = qa_manager.question_manager.get_tags_info_by_question_ids([_question_id]) v3_tags_info = qa_manager.question_manager.get_tags_v3_info_by_question_ids([_question_id]) result.update({ "v1_rel_tags_info": v1_tags_info.get(_question_id, []), "v3_rel_tags_info": v3_tags_info.get(_question_id, []), "rel_user_info": UserConvertService.get_user_info_by_user_id(question_obj.user_id) }) return result @bind("qa/answer/get_answer_rel_infos") def get_answer_rel_infos(answer_id): """ 获取回答关联的信息 :param answer_id: :return: """ result = {} if not answer_id: return result answer_obj = qa_manager.get_answer_objs( Q(pk=answer_id, is_online=True), None).only("id", "user", "question_id").first() if not answer_obj: return gen(ERROR.ANSWER_NOT_FOUND) _rel_question_id = answer_obj.question_id routine = GroupRoutine() _map_list = [ ("v1_rel_tags_info", qa_manager.question_manager.get_tags_info_by_question_ids, _rel_question_id, []), ("v3_rel_tags_info", qa_manager.answer_manager.get_tags_v3_info_by_answer_ids, answer_id, []), ("rel_user_info", UserConvertService.get_user_info_by_user_ids, answer_obj.user_id, {}), ] for key, func, param, _ in _map_list: routine.submit(key, func, [param]) routine.go() for key, _, param, _default in _map_list: _data = routine.results.get(key, {}) result.update({ key: _data.get(param, _default) }) return result @bind('qa/answer/answer_bulk_offline_by_ids') def answer_bulk_offline_by_ids(answer_ids, platform=None): """ 回答内容批量下线 :param answer_ids: :param platform: :return: """ if not answer_ids: return filter_query = Q(pk__in=list(map(int, answer_ids))) if platform and platform in GRABBING_PLATFORM: filter_query &= Q(platform=platform) nums = qa_manager.get_objs_by_query_and_order( model=qa_manager.answer_manager.model, query=filter_query ).update(is_online=False) return nums