# coding=utf-8 import datetime from gm_serializer import serializers from gm_types.gaia import USER_TYPE from gm_types.mimas.enum import MEDIA_IMAGE_URL_SOURCE, IMAGE_TYPE from qa import validators from qa.models import ( Question, QuestionImage, QuestionTag, Answer, AnswerImage, AnswerReply, AnswerVote, AnswerVoteReply, AnswerTag, QuestionTagV3 ) from qa.tasks.view import gif_create_webp from utils.rpc import get_current_user, RPCMixin, rpc_client from qa.utils.image import img_type, handle_image_type class QuestionImageSerializer(serializers.ModelSerializer): class Meta: model = QuestionImage fields = ('image_url', 'create_time', 'update_time', "width", "height", "image_url_source") class QuestionTagSerializer(serializers.ModelSerializer): tag = serializers.MagicField() class Meta: lazy_fields = ('tag',) model = QuestionTag fields = ('id', 'tag',) class QuestionSerializer(serializers.MagicSerializer): images = QuestionImageSerializer(many=True) tags = QuestionTagSerializer(many=True) user = serializers.MagicField( validators=[validators.BlacklistValidator()], ) content = serializers.CharField(allow_blank=True, allow_null=True, ) title = serializers.CharField() class Meta: model = Question lazy_fields = ('user',) fields = '__all__' def save_question_tag_v3(self, question, tags_data): """ 保存问题对应的新标签 :param question: 问题对象 :param tags_data: 老标签数据 [{'tag': 11, }] :return: """ # 获取老标签对应的新标签 old_tag_ids = [old_tag['tag'] for old_tag in tags_data] try: old_map_new_data_dict = rpc_client['api/tag_v3/get_map_new_tag_by_old_ids'](old_tag_ids=old_tag_ids).unwrap() except: old_map_new_data_dict = {} question_tag_v3_obj_list = list() for _, tag_v3_info_list in old_map_new_data_dict.items(): for tag_v3_info in tag_v3_info_list: question_tag_v3_obj_list.append( QuestionTagV3( question_id=question.id, tag_v3_id=tag_v3_info['id'] ) ) i = 0 bulk_count = 500 while i < len(question_tag_v3_obj_list): QuestionTagV3.objects.bulk_create(question_tag_v3_obj_list[i : i + bulk_count]) i += bulk_count def create(self, validated_data): """ question create :param validated_data: :return: """ images_data = validated_data.pop('images') tags_data = validated_data.pop('tags') question = Question.objects.create(**validated_data) image_urls = [image_data['image_url'] for image_data in images_data if image_data['image_url']] gevent_dic = handle_image_type(image_urls) gif_create_webp.delay(conent_id=question.id, content_type="question") image_list = list() for image_data in images_data: if image_data["image_url"]: question_image = QuestionImage( question=question, image_url=image_data['image_url'], width=image_data.get("width", 0), height=image_data.get("height", 0), image_url_source=image_data.get("image_url_source", MEDIA_IMAGE_URL_SOURCE.CREATE), image_type=gevent_dic.get(image_data['image_url'], IMAGE_TYPE.OTHER) or IMAGE_TYPE.OTHER, ) image_list.append(question_image) if image_list: QuestionImage.objects.bulk_create(image_list) for tag in tags_data: try: QuestionTag(question=question, tag=tag['tag']).save() except serializers.ValidationError: pass # 保存问题对应的新标签关系 self.save_question_tag_v3(question, tags_data) return question class AnswerTagSerializer(serializers.ModelSerializer): tag = serializers.MagicField() class Meta: lazy_fields = ('tag',) model = AnswerTag fields = ('id', 'tag',) class AnswerSerializer(serializers.MagicSerializer): images = QuestionImageSerializer(many=True) tags = AnswerTagSerializer(many=True) user = serializers.MagicField( validators=[validators.BlacklistValidator()] ) content = serializers.CharField() class Meta: model = Answer lazy_fields = ('user',) fields = '__all__' def create(self, validated_data): images_data = validated_data.pop('images') tags_data = validated_data.pop('tags') answer = Answer.objects.create(**validated_data) image_urls = [image_data['image_url'] for image_data in images_data if image_data['image_url']] gevent_dic = handle_image_type(image_urls) gif_create_webp.delay(conent_id=answer.id, content_type='answer') image_list = [] for image_data in images_data: if image_data["image_url"]: t = AnswerImage( answer=answer, image_url=image_data['image_url'], width=image_data.get("width", 0), height=image_data.get("height", 0), image_url_source=image_data.get("image_url_source", MEDIA_IMAGE_URL_SOURCE.CREATE), image_type=gevent_dic.get(image_data['image_url'], IMAGE_TYPE.OTHER) or IMAGE_TYPE.OTHER, ) image_list.append(t) if image_list: AnswerImage.objects.bulk_create(image_list) answer_tag_list = list() for tag in tags_data: answer_tag_list.append(AnswerTag(answer=answer, tag=tag['tag'])) if answer_tag_list: AnswerTag.objects.bulk_create(answer_tag_list) return answer class AnswerReplySerializer(serializers.MagicSerializer): answer = serializers.PrimaryKeyRelatedField(queryset=Answer.objects.all()) commented_reply = serializers.PrimaryKeyRelatedField(queryset=AnswerReply.objects.all(), allow_null=True) user = serializers.MagicField( validators=[validators.BlacklistValidator()] ) content = serializers.CharField( validators=[validators.FilterWordValidator(), validators.RepeatedValidator(AnswerReply, 'content')] ) class Meta: model = AnswerReply lazy_fields = ('user',) fields = '__all__' def create(self, validated_data): comment_reply = validated_data.pop('commented_reply') answer_reply = AnswerReply(**validated_data) if comment_reply: #二级评论 评论给评论 reply = AnswerReply.objects.get(pk=comment_reply.id) if reply.first_reply: answer_reply.first_reply_id = reply.first_reply_id else: answer_reply.first_reply_id = comment_reply.id answer_reply.commented_reply_id = comment_reply.id # 自己评论自己 则至为已读状态 if answer_reply.user_id == comment_reply.user_id: answer_reply.is_read = True answer_reply.save() else: #一级评论 评论给回答 answer = validated_data.get("answer") if answer_reply.user_id == answer.user_id: answer_reply.is_read = True answer_reply.save() answer_reply.answer.save() return answer_reply class AnswerVoteSerializer(serializers.MagicSerializer): answer = serializers.PrimaryKeyRelatedField(queryset=Answer.objects.all()) class Meta: model = AnswerVote lazy_fields = ('user',) fields = '__all__' def create(self, validated_data): vote = AnswerVote.objects.create(**validated_data) vote.answer.like_num += 1 vote.answer.save() return vote class AnswerReplyVoteSerializer(serializers.MagicSerializer): user = serializers.MagicField() answerreply = serializers.PrimaryKeyRelatedField(queryset=AnswerReply.objects.all()) class Meta: model = AnswerVoteReply lazy_fields = ('user',) fields = '__all__' def create(self, validated_data): vote = AnswerVoteReply.objects.create(**validated_data) vote.answerreply.like_num += 1 vote.answerreply.save() return vote class AnswerListSerializer(serializers.MagicSerializer): author = serializers.SerializerMethodField() comment_count = serializers.IntegerField(source="comment_num") is_voted = serializers.SerializerMethodField() user_type = serializers.SerializerMethodField() images = serializers.SerializerMethodField() create_time = serializers.SerializerMethodField() replies = serializers.SerializerMethodField() first_reply_count = serializers.IntegerField(source="first_reply_num") # 新增返回一级评论数,用于加载更多 def get_user_type(self, obj): return USER_TYPE.NORMAL def get_author(self, obj): return { 'user_id': obj.user.id, 'user_type': USER_TYPE.NORMAL, 'user_name': obj.user.nickname, 'user_portrait': obj.user.portrait, 'membership_level': obj.user.membership_level, 'user_level': { 'membership_icon': obj.user.membership_icon, 'level_icon': obj.user.level_icon, 'constellation_icon': obj.user.constellation_icon, }, "college_id": obj.user.get("college_id", 0), "college_name": obj.user.get("college_name", ""), } def get_is_voted(self, obj): user = get_current_user() if user: return AnswerVote.objects.filter(answer=obj, user=user.id).exists() return False def get_images(self, obj): return [image.image_url for image in obj.images.filter(image_url_source=MEDIA_IMAGE_URL_SOURCE.CREATE).all()] def get_create_time(self, obj): return obj.create_time.strftime('%y-%m-%d %H:%M') def get_replies(self, obj): replies = AnswerReply.objects.filter(answer=obj, first_reply__isnull=True, is_online=True).order_by("create_time")[:2] return [reply.get_data_for_reply(new_order=True) for reply in replies] class Meta: model = Answer lazy_fields = ('user',) fields = ( 'id', 'create_time', 'content', 'author', 'user_type', 'is_voted', 'comment_count', 'like_num', 'images', 'platform', 'replies', 'first_reply_count','is_recommend', 'video_cover_list', )