# coding=utf-8 from __future__ import unicode_literals, absolute_import, print_function import datetime from gm_types.mimas import CONTENT_CLASS from django.conf import settings from django.db.models import Max, Q from gm_types.error import ERROR as CODES from gm_types.mimas.enum import MEDIA_IMAGE_URL_SOURCE from qa.models.answer import Question, Answer, AnswerVote, \ AnswerReply, QuestionTag from qa.service import QaFavorServices from qa.tasks import add_question_view from gm_rpcd.all import bind from talos.cache.base import favor_cache from talos.tools.favor_tool import FavorTool from utils.rpc import gen, logging_exception, get_current_user @bind('qa/question/polymers_extra') def polymers_extra(polymers): # 新增问题数 + 新增回答数 + 新增评论数 + 新增点赞数 date = datetime.date.today() - datetime.timedelta(days=1) if not isinstance(polymers, list): return {} items = {} for polymer in polymers: item = { "new_question_cnt": 0, "new_answer_cnt": 0, "new_vote_cnt": 0, "new_reply_cnt": 0, } question_types = polymer.get("question_types", []) if question_types: item["new_question_cnt"] = Question.objects.filter( question_type__in=question_types, create_time__year=date.year, create_time__month=date.month, create_time__day=date.day, ).count() item["new_answer_cnt"] = Answer.objects.filter( question__question_type__in=question_types, question__create_time__year=date.year, question__create_time__month=date.month, question__create_time__day=date.day, ).count() item["new_vote_cnt"] = AnswerVote.objects.filter( answer__question__question_type__in=question_types, answer__question__create_time__year=date.year, answer__question__create_time__month=date.month, answer__question__create_time__day=date.day, ).count() item["new_reply_cnt"] = AnswerReply.objects.filter( answer__question__question_type__in=question_types, answer__create_time__year=date.year, answer__create_time__month=date.month, answer__create_time__day=date.day, ).count() tags = polymer.get("tags", []) if tags: questions_ids = QuestionTag.objects.filter(tag__in=tags).values_list("question_id", flat=True) item["new_question_cnt"] += Question.objects.filter( pk__in=questions_ids, create_time__year=date.year, create_time__month=date.month, create_time__day=date.day, ).count() item["new_answer_cnt"] += Answer.objects.filter( question__pk__in=questions_ids, question__create_time__year=date.year, question__create_time__month=date.month, question__create_time__day=date.day, ).count() item["new_vote_cnt"] += AnswerVote.objects.filter( answer__question__pk__in=questions_ids, answer__question__create_time__year=date.year, answer__question__create_time__month=date.month, answer__question__create_time__day=date.day, ).count() item["new_reply_cnt"] += AnswerReply.objects.filter( answer__question__pk__in=questions_ids, answer__create_time__year=date.year, answer__create_time__month=date.month, answer__create_time__day=date.day, ).count() items[str(polymer["id"])] = item return items @bind('qa/question_total_count_by_tag_ids') def get_question_count_by_tag_ids(tag_ids): t_q_count = QuestionTag.objects.filter(tag__in=tag_ids).values_list('question_id', flat=True).distinct().count() #t_a_count = QuestionTag.objects.filter(tag__in=tag_ids).values_list('question__answers', flat=True).distinct().count() t_a_count = Answer.objects.filter(question__qtags__tag__in=tag_ids).values_list('id', flat=True).distinct().count() return { 'question_count': t_q_count, 'answer_count': t_a_count } @bind('qa/question/get_qa_data') def get_qa_data(user_id, start_num=0, count=10): if not user_id: return gen(CODES.PARAMS_INVALID) try: answer = Answer.objects.filter(user=user_id, is_online=True).\ order_by('-update_time')[start_num:start_num+count] except: logging_exception() return gen(CODES.ANSWER_NOT_FOUND) qa_data = { "qa": [] } for item in answer: data = { 'answer_content': item.content, 'answer_id': item.id, 'question_id': item.question.id, 'question_content': item.question.content, 'images': [image.image_url for image in item.images.filter( image_url_source=MEDIA_IMAGE_URL_SOURCE.CREATE).all()], 'question_title': item.question.title, } qa_data['qa'].append(data) return qa_data @bind("qa/question/list_for_web_by_ids") def get_qa_card_by_ids_for_web(question_ids): """ pc站,m站问答卡片列表数据 :param question_ids: :return: """ assert isinstance(question_ids, list) assert len(question_ids) <= 100 user = get_current_user() questions = Question.objects.filter(is_online=True, id__in=question_ids) question_dict = {} for question_item in questions: _q_id = question_item.id _q_data = question_item.data_for_my_list(need_view_amount=False) _q_data.update({ 'user_id': question_item.user.id, 'user_name': question_item.user.nickname, 'user_portrait': question_item.user.portrait, 'timestamp': int(question_item.create_time.strftime("%s")), }) question_dict[str(_q_id)] = {"question": _q_data} question_ids = list(map(int, question_dict.keys())) _answer_ids = list(Answer.objects.filter( is_online=True, question_id__in=question_ids, level__in=[CONTENT_CLASS.BAD, CONTENT_CLASS.GENERAL, CONTENT_CLASS.FINE, CONTENT_CLASS.EXCELLENT, CONTENT_CLASS.OUTSTANDING] ).values("question_id").annotate(_id=Max("id")).values_list("_id", flat=True)) answers = Answer.objects.filter(id__in=_answer_ids) for answer in answers: _question_id = str(answer.question_id) _question_dict = question_dict.get(_question_id, {}) if _question_dict: _question_dict["answer"] = answer.data_for_es(need_view_amount=False) return { "qa_cards": question_dict, } @bind("qa/quetion/get_random_questions_for_seo") def get_random_questions_for_pc(count=10): """ 为pc站随机获取问题数据 :return: """ result = { "questions": [], } _sql = "SELECT id, title FROM api_question WHERE is_online=1 and id >= (" \ "((SELECT MAX(id) FROM api_question) - (SELECT MIN(id) FROM api_question)) * RAND() + (SELECT MIN(id) FROM api_question)" \ ") limit {_count};".format(_count=count) for q_obj in Question.objects.using(settings.SLAVE_DB_NAME).raw(_sql): _dic = { "question_id": q_obj.id, "title": q_obj.title, } result["questions"].append(_dic) return result @bind("qa/question/get_share_data") def get_question_share_data_by_id(question_id): try: question = Question.objects.get(pk=question_id) except Question.DoesNotExist: return gen(CODES.QUESTION_NOT_FOUND) user = get_current_user() user_id = user and user.id if not question.user_can_view(user_id): return gen(CODES.QUESTION_NOT_FOUND) base_query = Q(question_id=question_id, is_online=True) _recommend_answer = Answer.objects.filter(base_query & Q(is_recommend=True)).first() if _recommend_answer: answer = _recommend_answer else: _hot_answer = Answer.objects.filter( base_query & Q(is_recommend=False, like_num__gte=4)).order_by("rank", "-like_num", "-id").first() if _hot_answer: answer = _hot_answer else: _last_answer = Answer.objects.filter( base_query & Q(is_recommend=False, like_num__gte=2)).order_by("-update_time").first() if _last_answer: answer = _last_answer else: answer = None _data = { "question_id": question_id, "answer_id": answer and answer.id or 0, "answer_content": answer and answer.content or "", "question_content": question.content, "question_tags": [tag_obj.tag for tag_obj in question.tags], "question_old_images": question.content_images, "answer_old_images": answer and answer.content_images or [], "answer_num": question.answer_num, } return _data @bind("mimas/question/list") def get_question_list_by_user_id(user_id, offset=0, count=10): questions = Question.objects.filter(user=user_id, is_online=True).order_by('-id')[offset:offset+count] question_ids = [question.id for question in questions] result = [question.data_for_my_list() for question in questions] #增加浏览量 add_question_view.delay(question_ids) return result @bind('mimas/qa/favor') def qa_favor_create(question_id=None, answer_id=None): """ 问题或回答的收藏 :param question_id: :param answer_id: :return: """ if not any([question_id, answer_id]): return gen(CODES.PARAMS_INCOMPLETE) if answer_id: answer = QaFavorServices.answer_healthy(answer_id) if question_id: question = QaFavorServices.question_healthy(question_id) user = get_current_user() if not user: return gen(CODES.LOGIN_REQUIRED) result = QaFavorServices.create(user_id=user.id, question_id=question_id, answer_id=answer_id) if answer_id: favor_tool = FavorTool(redis_c=favor_cache, user_id=answer.user_id) favor_tool.receive_answer_favor(result.get('id')) else: favor_tool = FavorTool(redis_c=favor_cache, user_id=question.user_id) favor_tool.receive_question_favor(result.get('id')) return result @bind('qa/favor/bulk_favor_question') def bulk_favor_question(user_id, question_ids): """ 内部调用接口,批量关注问题。不关注返回值 :param user_id: :param question_ids: :return: """ for question_id in question_ids: try: question = QaFavorServices.question_healthy(question_id) result = QaFavorServices.create(user_id=user_id, question_id=question_id) favor_tool = FavorTool(redis_c=favor_cache, user_id=question.user_id) favor_tool.receive_question_favor(result.get('id')) except: continue @bind('mimas/qa/favor/cancel') def qa_favor_cancel(question_id=None, answer_id=None): """ 问题或回答的收藏取消 :param question_id: :param answer_id: :return: """ if not any([question_id, answer_id]): return gen(CODES.PARAMS_INCOMPLETE) if answer_id: answer = QaFavorServices.answer_healthy(answer_id) if question_id: question = QaFavorServices.question_healthy(question_id) user = get_current_user() if not user: return gen(CODES.LOGIN_REQUIRED) result = QaFavorServices.cancel(user_id=user.id, question_id=question_id, answer_id=answer_id) if answer_id: favor_tool = FavorTool(redis_c=favor_cache, user_id=answer.user_id) favor_tool.remove_answer_favor(result.get('id')) else: favor_tool = FavorTool(redis_c=favor_cache, user_id=question.user_id) favor_tool.remove_question_favor(result.get('id')) return result @bind('mimas/attention_page/questions') def attention_page_question_list(question_ids): """ 消息-关注页面问题列表 :param question_ids: :return: """ if not question_ids: return [] question_ids = list(map(int, question_ids)) questions = Question.objects.using(settings.SLAVE_DB_NAME).filter( id__in=question_ids) data = [] for question in questions: data.append(question.data_for_list()) add_question_view.delay(question_ids) return data @bind('mimas/qa_favor/read') def qa_favor_read_all(): """ 消息页收藏tab 问答收藏已读 :return: """ user = get_current_user() if not user: return gen(CODES.SUCCESS) QaFavorServices.message_favor_tab_read(user.id) return gen(CODES.SUCCESS) @bind('mimas/qa_favor/get_unread_count') def qa_favor_get_unread_count(): """ 消息页收藏tab 问答收藏已读 :return: """ result = { 'count': 0 } user = get_current_user() if not user: return result question_unread_count = QaFavorServices.get_message_tab_question_favor_count(user.id) answer_unread_count = QaFavorServices.get_message_tab_answer_favor_count(user.id) result['count'] = question_unread_count.get('count', 0) + answer_unread_count.get('count', 0) return result